gpt4 book ai didi

mongodb - 聚合 $lookup 不返回元素原始数组顺序

转载 作者:可可西里 更新时间:2023-11-01 10:08:40 26 4
gpt4 key购买 nike

查询返回元素在其集合中的放置顺序,忽略初始数组的顺序。这会影响我们系统的功能。是否有任何额外的命令可以将其按正确的顺序排列?是否有可用的解决方法?

下面是一个简单的例子:

Collection1 文档

{
"_id":ObjectId("5c781752176c512f180048e3"),
"Name":"Pedro",
"Classes":[
{"ID": ObjectId("5c7af2b2f6f6e47c9060d7ce") },
{"ID": ObjectId("5c7af2bcf6f6e47c9060d7cf") },
{"ID": ObjectId("5c7af2aaf6f6e47c9060d7cd") }
]
}

Collection2 文档

{
"_id":ObjectId("5c7af2aaf6f6e47c9060d7cd"),
"variable1":"A"
},

{
"_id": ObjectId("5c7af2b2f6f6e47c9060d7ce"),
"variable1":"B"
},

{
"_id": ObjectId("5c7af2bcf6f6e47c9060d7cf"),
"variable1":"C"
}

查询:

aggregate(
pipeline = '[
{"$match": {"_id": {"$oid": "5c781752176c512f180048e3"}}},
{"$lookup": {"from": "collection2", "localField": "Classes.ID", "foreignField": "_id", "as": "Collection2_doc"}}
]'
)

返回:

结果顺序:

[
{
"_id":ObjectId("5c7af2aaf6f6e47c9060d7cd"),
"variable1":"A"
},
{
"_id": ObjectId("5c7af2b2f6f6e47c9060d7ce"),
"variable1":"B"
},
{
"_id": ObjectId("5c7af2bcf6f6e47c9060d7cf"),
"variable1":"C"
}
]

预期顺序(第一个文档数组顺序):

[
{
"_id": ObjectId("5c7af2b2f6f6e47c9060d7ce"),
"variable1":"B"
},
{
"_id": ObjectId("5c7af2bcf6f6e47c9060d7cf"),
"variable1":"C"
},
{
"_id":ObjectId("5c7af2aaf6f6e47c9060d7cd"),
"variable1":"A"
}
]

有没有额外的命令ex。 $sort 可用于根据原始数组顺序返回它?

最佳答案

这是 $lookup 的“设计”执行。 实际上发生的“幕后”是MongoDB 内部转换$lookup中的参数使用 $expr 转换为新的表现力 格式和 $in .即使在实现这种富有表现力的形式之前的版本中,“值数组”的内部机制也几乎相同。

这里的解决方案是维护原始数组的副本作为重新排序“已加入” 项目的引用:

collection.aggregate([
{"$match": {"_id": ObjectId("5c781752176c512f180048e3") }},
{"$lookup": {
"from": "collection2",
"let": { "classIds": "$Classes.ID" },
"pipeline": [
{ "$match": {
"$expr": { "$in": [ "$_id", "$$classIds" ] }
}},
{ "$addFields": {
"sort": {
"$indexOfArray": [ "$$classIds", "$_id" ]
}
}},
{ "$sort": { "sort": 1 } },
{ "$addFields": { "sort": "$$REMOVE" }}
],
"as": "results"
}}
])

或由遗产$lookup用法:

collection.aggregate([
{"$match": {"_id": ObjectId("5c781752176c512f180048e3") }},
{"$lookup": {
"from": "collection2",
"localField": "Classes.ID",
"foreignField": "_id",
"as": "results"
}},
{ "$unwind": "$results" },
{ "$addFields": {
"sort": {
"$indexOfArray": [ "$Classes.ID", "$results._id" ]
}
}},
{ "$sort": { "_id": 1, "sort": 1 } },
{ "$group": {
"_id": "$_id",
"Name": { "$first": "$Name" },
"Classes": { "$first": "$Classes" },
"results": { "$push": "$results" }
}}
])

两种变体产生相同的输出:

{
"_id" : ObjectId("5c781752176c512f180048e3"),
"Name" : "Pedro",
"Classes" : [
{
"ID" : ObjectId("5c7af2b2f6f6e47c9060d7ce")
},
{
"ID" : ObjectId("5c7af2bcf6f6e47c9060d7cf")
},
{
"ID" : ObjectId("5c7af2aaf6f6e47c9060d7cd")
}
],
"results" : [
{
"_id" : ObjectId("5c7af2b2f6f6e47c9060d7ce"),
"variable1" : "B"
},
{
"_id" : ObjectId("5c7af2bcf6f6e47c9060d7cf"),
"variable1" : "C"
},
{
"_id" : ObjectId("5c7af2aaf6f6e47c9060d7cd"),
"variable1" : "A"
}
]
}

一般概念是使用 $indexOfArray“加入” 内容中的 _id 值进行比较,以找到它在 中的原始源数组中的 “索引” 位置$Classes.ID”。不同的$lookup语法变体对于您如何访问此副本以及您如何基本重构有不同的方法。

$sort当然设置了实际文档的顺序,要么在表达形式的流水线处理中,要么通过$unwind 的公开文档。 .你在哪里使用$unwind然后你会$group回到原来的文档形式。

NOTE: The usage examples here depend on MongoDB 3.4 for the $indexOfArray at least and the $$REMOVE aligns with MongoDB 3.6 as would the expressive $lookup.

There are other approaches to re-ordering the array for prior releases, but these are demonstrated in more detail on Does MongoDB's $in clause guarantee order. Realistically the bare minimum you should presently be running as a production MongoDB version is the 3.4 release.

See Support Policy under MongoDB Server for the full details of supported releases and end dates.

关于mongodb - 聚合 $lookup 不返回元素原始数组顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55033804/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com