Mongo:从多个集合中过滤文档并合并

时间:2019-06-08 07:35:36

标签: node.js mongodb mongoose

我是mongo和NodeJS的新手,有一个用例,我想从多个集合中获取经过过滤的结果。

对于冗长的帖子提前致歉。

例如: collectionA

{
    "_id" : "foo@gmail.com",
    "name" : "Foo",
    "location" : {
        "coordinates" : [
            -122.420170,
            37.780080
        ],
        "type" : "Point"
    }
},
{
    "_id" : "bar@gmail.com,
    "name" : "Bar",
    "location" : {
        "coordinates" : [
            -122.420060,
            37.780180
        ],
        "type" : "Point"
    }
}

collectionB:并非所有文档都具有某些属性,因此是可选的

{
    "_id" : "foo@gmail.com"
    "AttributeA" : [
        {
            "name" : "AttA_Name",
            "val" : "Coll_B_AttA_Val_Foo"
        },
        {
            "name" : "AttA_Name1",
            "val" : "Coll_B_AttA_Val_Foo"
        }]
},
{
    "_id" : "bar@gmail.com"
    "AttributeA" : [
        {
            "name" : "AttA_Name",
            "val" : "Coll_B_AttA_Val_Bar"
        },
        {
            "name" : "AttA_Name2",
            "val" : "Coll_B_AttA_Val_Bar"
        }
    ],
   "AttributeB" : [
        {
            "name" : "AttB_Name",
            "val" : "Coll_B_AttB_Val_Bar"
        }
    ]
}

CollectionC:并非所有文档都包含某些属性,因此是可选的

{
    "_id" : "foo@gmail.com"
    "AttributeA" : [
        {
            "name" : "Coll_C_AttA_Name",
            "val" : "Coll_C_AttA_Val_Foo"
        }]
},
{
    "_id" : "bar@gmail.com"
    "AttributeA" : [
        {
            "name" : "Coll_C_AttA_Name",
            "val" : "Coll_C_AttA_Val_Bar"
        }
    ],
   "AttributeB" : [
        {
            "name" : "Coll_C_AttB_Name",
            "val" : "Coll_C_AttB_Val_Bar"
        }
    ]
}

我知道集合B和C的架构看起来相同,但目的不同,而且必须有所不同。数据库设计不是问题,因此,如果不全神贯注,我将不胜感激。

查询: 假定存在另一个与Bar具有相同属性的用户(Alan),该用户存在于集合中,但不在Bar的位置附近。

我要在这些查询之上构建的查询是

  1. 从CollectionA查找居住在附近的人
  2. 还有集合B,如果AttributeA存在并且具有一个名称为AttA_Name的元素
  3. 在集合C中,如果AttributeA存在并且具有名称:Coll_C_AttA_Name

在上述情况下,我期望结果为

{
    "_id" : "foo@gmail.com",
    "name" : "Foo",
    "location" : {
        "coordinates" : [
            -122.420170,
            37.780080
        ],
        "type" : "Point"
    },
    "collectionB_AttributeA" : [
        {
            "name" : "AttA_Name",
            "val" : "Coll_B_AttA_Val_Foo"
        },
        {
            "name" : "AttA_Name1",
            "val" : "Coll_B_AttA_Val_Foo"
        }]
     ,
    "collectionC_AttributeA" : [
        {
            "name" : "Coll_C_AttA_Name",
            "val" : "Coll_C_AttA_Val_Foo"
        }]
},
{
    "_id" : "bar@gmail.com,
    "name" : "Bar",
    "location" : {
        "coordinates" : [
            -122.420060,
            37.780180
        ],
        "type" : "Point"
    },
    "collectionB_AttributeA":[
        {
            "name" : "AttA_Name",
            "val" : "Coll_B_AttA_Val_Bar"
        },
        {
            "name" : "AttA_Name2",
            "val" : "Coll_B_AttA_Val_Bar"
        }
    ],
    "collectionC_AttributeA":[
        {
            "name" : "Coll_C_AttA_Name",
            "val" : "Coll_C_AttA_Val_Bar"
        }
    ]

}

有一种方法可以分为几部分:

  1. 查询集合A并找到附近的人
  2. 浏览1的结果,并在CollectionB中查找它们是否具有AttributeA和名称为AttA_Name的元素,并消除它们是否不匹配。
  3. 浏览2中的筛选结果,并在CollectionC中查找它们是否具有AttributeA和名称为Coll_C_AttA_Name的元素,以及它们是否没有消除此类文档。

有没有一种方法可以使用聚合将此查询构建为一个?我尝试阅读并尝试汇总,但似乎我的理解还不完善。

        let result = await CollectionASchema.aggregate([
            {
              $geoNear: {
                 near: { type: "Point", coordinates: [ Number(long) , Number(lat) ] },
                 distanceField: "dist.calculated",
                 minDistance: 0,
                 maxDistance: radiusinmetres,
                 spherical: true
              }
            },
            {
                $lookup:
                   {
                     from: 'collectionB',
                     pipeline: [
                        { $match : { $and: [{ AttributeA :{$exists: true}}, { [category]: { $elemMatch: { name: “AttA_Name” } } }] }},
                        { $project: { AttributeA: 0 } }
                     ],
                     as: "collectionB_AttributeA"
                   }
              }
         ])

如果您可以解释这是否可行,或者让我知道这是有用的正确方法。

0 个答案:

没有答案