通过对象中已有的数据查询

时间:2019-07-16 05:08:30

标签: node.js mongodb aggregation-framework

我正在编写一个查询,该查询基于“ coll1”内部的数据从“ coll2”获取数据。

Coll1具有以下数据结构:

class RowReader:
    def fileRead(self,filepath):
        file = open(filepath,"r")
        for line in file:
            row_data = line.strip("\n").split(',')
            print("student no : {}\nName : {}\nSurname : {}".format(
        row_data[0], row_data[1], row_data[2]))

file = RowReader()
file.fileRead("filepath")

Coll2具有以下数据结构:

{
  "_id": "asdf",
  "name": "John",
  "bags": [
    {
       "type": "typ1",
       "size": "siz1"
    },
    {
       "type": "typ2",
       "size": "siz2"
    }
  ]
}

我想使用聚合管道的{ _id: "qwer", coll1Name: "John", types: ["typ1", "typ3"], sizes: ["siz1", "siz4"] } { _id: "zxcv", coll1Name: "John", types: ["typ2", "typ3"], sizes: ["siz1", "siz2"] } { _id: "fghj", coll1Name: "John", types: ["typ2", "typ3"], sizes: ["siz1", "siz4"] } 阶段来获取coll2中所有具有与coll1中相同的Type + Size组合的文档。我了解可以通过使用$lookup$lookup pipeline来实现,但是我似乎无法弄清楚如何动态地进行查询以传递到$expr阶段。

我想获取上述数据的输出为:

$match

2 个答案:

答案 0 :(得分:1)

您可以使用$lookupCol2获取数据。然后,您需要检查Col2$anyElemenTrue)中是否有与Col1相匹配的元素。 $map$in可以在这里使用。然后,您只需要$unwind并使用$replaceRoot

Col2提升到根级别
db.Col1.aggregate([
    {
        $lookup: {
            from: "Col2",
            localField: "name",
            foreignField: "coll1Name",
            as: "Col2"
        }
    },
    {
        $project: {
            Col2: {
                $filter: {
                    input: "$Col2",
                    as: "c2",
                    cond: {
                        $anyElementTrue: {
                            $map: {
                                input: "$bags",
                                as: "b",
                                in: {
                                    $and: [
                                        { $in: [ "$$b.type", "$$c2.types" ] },
                                        { $in: [ "$$b.size", "$$c2.sizes"  ] },
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        $unwind: "$Col2"
    },
    {
        $replaceRoot: {
            newRoot: "$Col2"
        }
    }
])

答案 1 :(得分:1)

您正确的做法是将 $lookup 与管道字段一起使用来过滤 $match 管道中的输入文档 $expr 表达式通常应遵循

"$expr": { 
    "$and": [
        { "$eq": [ "$name",  "$$coll1_name" ] },
        { "$setEquals": [ "$bags.type", "$$types" ] },
        { "$setEquals": [ "$bags.size", "$$sizes" ] }
    ]
}

其中,条件{ "$eq": [ "$name", "$$coll1_name" ] }中的 $and 中的第一个匹配表达式检查name集合中的coll1字段是否与{{ coll1Name中输入文档中的1}}字段。 当然,coll2中的字段应该在管道中的变量中定义,其中coll2字段供 $lookup 管道访问。

其他匹配过滤器基本上是在检查数组是否相等,其中let的{​​{1}}解析为"$bags.type"的数组,例如coll1

从正好是数组的 $lookup 获取输出字段时,您可以过滤该数组字段上types中的文档,其中可以有一些空列表作为上述 $lookup 管道$ match过滤器的结果:

[ "typ1", "typ3" ]

总体而言,总的流水线操作如下:

coll2