我想在2个集合中进行$ lookup查询,其中第1个集合有单个点,第2个集合中有多边形...现在我想查询多边形内的所有点并从第1个集合构建平均值
我的实际汇总:
'aggregation': {
'pipeline': [
# must match the field location from my first collection
{ "$match": {
"location" : "$loc"
} },
# lookup to join location from 1st collection and geometry from 2nd collection
{ "$lookup": {
"from": "polygons",
"localField": "location",
"foreignField": "geometry",
"as": "join" } },
# output grouped
{ "$group": {
"_id": "Average",
"Geometry": "$join.geometry" ,
"AvgVal": { "$avg": "$myVal" } ,
"count": {"$sum": 1} } },
]
}
我希望任何人都能理解我的意思; - )
编辑: 文件1:
{ id: "ABC", location: {type: "point", coordinates: [0,1]}, myVal: 1 },
{ id: "DEF", location: {type: "point", coordinates: [2,3]}, myVal: 2 }
{ id: "GHI", location: {type: "point", coordinates: [9,8]}, myVal: 3 }
{ id: "JKL", location: {type: "point", coordinates: [7,6]}, myVal: 4 }
{ id: "MNO", location: {type: "point", coordinates: [5,4]}, myVal: 5 }
文件2:
{ id: "Vienna Part1", geometry: {type: "polygon", coordinates: [[[0,1],[1,2],[2,3],[0,1]]] } },
{ id: "Vienna Part2", geometry: {type: "polygon", coordinates: [[[9,8],[7,6],[5,4],[9,8]]] } },
现在我发送一个带有多边形的查询(我的屏幕上的地图):$ geoIntersect polygon .. [0,1] ... [9,8]
预期:
{ id: "Vienna Part1", AvgVal: 1.5, geometry: {type: "polygon", coordinates: [[[0,1],[1,2],[2,3],[0,1]]] }
{ id: "Vienna Part2", AvgVal: 4, geometry: {type: "polygon", coordinates: [[[9,8],[7,6],[5,4],[9,8]]] }
LG 哈拉尔德
答案 0 :(得分:2)
您似乎并不理解$lookup
的概念是,对于要在查找中“匹配”的字段,它必须具有相同的数据。由于一个文档中包含的数据是以“多边形”表示法在数组中“双重嵌套”,因此需要$unwind
数组内容“两次”以获得“匹配”。
作为一个整体的例子,让我们用你的“点”文档创建一个集合:
db.geo1.insertMany([
{ _id: "ABC", location: {type: "point", coordinates: [0,1]}, myVal: 1 },
{ _id: "DEF", location: {type: "point", coordinates: [2,3]}, myVal: 2 },
{ _id: "GHI", location: {type: "point", coordinates: [9,8]}, myVal: 3 },
{ _id: "JKL", location: {type: "point", coordinates: [7,6]}, myVal: 4 },
{ _id: "MNO", location: {type: "point", coordinates: [5,4]}, myVal: 5 }
])
另一个包括“多边形”文件,故意包括一个不匹配的文件:
db.geo2.insertMany([
{ _id: "Vienna Part1", geometry: {type: "polygon", coordinates: [[[0,1],[1,2],[2,3],[0,1]]] } },
{ _id: "Vienna Part2", geometry: {type: "polygon", coordinates: [[[9,8],[7,6],[5,4],[9,8]]] } },
{ _id: "Vienna Part3", geometry: {type: "polygon", coordinates: [[[10,1],[10,3],[3,10],[10,1]]] } }
])
为了检查geo2
集合中geo1
中通过相同点坐标“相交”的项目,您必须执行以下操作:
db.geo2.aggregate([
{ "$unwind": "$geometry.coordinates" },
{ "$unwind": "$geometry.coordinates" },
{ "$lookup": {
"from": "geo1",
"localField": "geometry.coordinates",
"foreignField": "location.coordinates",
"as": "geo1"
}},
{ "$group": {
"_id": "$_id",
"coordinates": {
"$push": "$geometry.coordinates"
},
"matches": {
"$push": { "$ne": [ "$geo1", [] ] }
}
}},
{ "$redact": {
"$cond": {
"if": { "$anyElementTrue": "$matches" },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project" : {
"geometry": {
"type": { "$literal": "polygon" },
"coordinates": ["$coordinates"]
}
}},
{ "$sort": { "_id": 1 } }
])
所以第一件事是双$unwind
来从数组中获取“点”数据。然后你可以做$lookup
。
{ "_id" : "Vienna Part1", "geometry" : { "type" : "polygon", "coordinates" : [ 0, 1 ] }, "geo1" : [ { "_id" : "ABC", "location" : { "type" : "point", "coordinates" : [ 0, 1 ] }, "myVal" : 1 } ] }
{ "_id" : "Vienna Part1", "geometry" : { "type" : "polygon", "coordinates" : [ 1, 2 ] }, "geo1" : [ ] }
{ "_id" : "Vienna Part1", "geometry" : { "type" : "polygon", "coordinates" : [ 2, 3 ] }, "geo1" : [ { "_id" : "DEF", "location" : { "type" : "point", "coordinates" : [ 2, 3 ] }, "myVal" : 2 } ] }
{ "_id" : "Vienna Part1", "geometry" : { "type" : "polygon", "coordinates" : [ 0, 1 ] }, "geo1" : [ { "_id" : "ABC", "location" : { "type" : "point", "coordinates" : [ 0, 1 ] }, "myVal" : 1 } ] }
{ "_id" : "Vienna Part2", "geometry" : { "type" : "polygon", "coordinates" : [ 9, 8 ] }, "geo1" : [ { "_id" : "GHI", "location" : { "type" : "point", "coordinates" : [ 9, 8 ] }, "myVal" : 3 } ] }
{ "_id" : "Vienna Part2", "geometry" : { "type" : "polygon", "coordinates" : [ 7, 6 ] }, "geo1" : [ { "_id" : "JKL", "location" : { "type" : "point", "coordinates" : [ 7, 6 ] }, "myVal" : 4 } ] }
{ "_id" : "Vienna Part2", "geometry" : { "type" : "polygon", "coordinates" : [ 5, 4 ] }, "geo1" : [ { "_id" : "MNO", "location" : { "type" : "point", "coordinates" : [ 5, 4 ] }, "myVal" : 5 } ] }
{ "_id" : "Vienna Part2", "geometry" : { "type" : "polygon", "coordinates" : [ 9, 8 ] }, "geo1" : [ { "_id" : "GHI", "location" : { "type" : "point", "coordinates" : [ 9, 8 ] }, "myVal" : 3 } ] }
{ "_id" : "Vienna Part3", "geometry" : { "type" : "polygon", "coordinates" : [ 10, 1 ] }, "geo1" : [ ] }
{ "_id" : "Vienna Part3", "geometry" : { "type" : "polygon", "coordinates" : [ 10, 3 ] }, "geo1" : [ ] }
{ "_id" : "Vienna Part3", "geometry" : { "type" : "polygon", "coordinates" : [ 3, 10 ] }, "geo1" : [ ] }
{ "_id" : "Vienna Part3", "geometry" : { "type" : "polygon", "coordinates" : [ 10, 1 ] }, "geo1" : [ ] }
结果数据显示文档中新数组元素geo1
内"geo1"
集合中的“匹配”元素。这是一种“左连接”,所以有一个包含任何匹配的数组或一个空数组。
您的下一点是我们希望$group
返回更像原始文档表单的内容,在这里我们测试$lookup
的结果是否产生了一个空数组。这意味着在其他集合中“找不到”相应的文档:
{
"_id" : "Vienna Part3",
"coordinates" : [ [ 10, 1 ], [ 10, 3 ], [ 3, 10 ], [ 10, 1 ] ],
"matches" : [ false, false, false, false ]
}
{
"_id" : "Vienna Part2",
"coordinates" : [ [ 9, 8 ], [ 7, 6 ], [ 5, 4 ], [ 9, 8 ] ],
"matches" : [ true, true, true, true ]
}
{
"_id" : "Vienna Part1",
"coordinates" : [ [ 0, 1 ], [ 1, 2 ], [ 2, 3 ], [ 0, 1 ] ],
"matches" : [ true, false, true, true ]
}
您应该看到的是,其中一个文档的结果为"matches"
数组,其中每个元素都为false
。这对于以下$redact
条件非常重要,该条件使用$anyElementTrue
对该数组进行测试。
因此,在文档中看到所有元素都为false
的数组,这意味着这个特定点集合没有“交集”。因此,该文件将通过$$PRUNE
被丢弃,其中包含“至少一个”true
的其他文件将被保留。
唯一剩下的是一些小的化妆品转换,以回馈所需的结果:
{
"_id" : "Vienna Part1",
"geometry": {
"type": "polygon",
"coordinates" : [[ [ 0, 1 ], [ 1, 2 ], [ 2, 3 ], [ 0, 1 ] ]]
}
}
{
"_id" : "Vienna Part2",
"geometry": {
"type": "polygon",
"coordinates" : [[ [ 9, 8 ], [ 7, 6 ], [ 5, 4 ], [ 9, 8 ] ]]
}
}
当然,不同的几何类型会使这个过程复杂化,但这仍然是基本过程。
为了$lookup
,您必须将数据转换为与正在检查的目标收集字段相匹配的表单。
在“set”中查看结果时,您可以测试每个元素的逻辑结果,然后使用$anyElementTrue
进行评估。这将告诉您是否匹配某些内容而不会破坏各个元素。
因此,与第一个条件一样,第二个条件确保包含与其他集合中的“所有”文档不匹配的点的"Vienna Part1"
文档也匹配,因为“至少有一个“元素对匹配进行了true
评估。
这些是规则。所以我希望你现在能更好地理解它。