我正在编写一个查询,该查询基于“ 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
答案 0 :(得分:1)
您可以使用$lookup从Col2
获取数据。然后,您需要检查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