Като се има предвид „вдлъбнатината“, която използвам в списъка, това всъщност може да изглежда по-дълго от това, което правите, но всъщност не е.
Това е друг наистина добър пример за използване на $ карта
както е достъпно за MongoDB 2.6 и по-нова версия. Все още има известна употреба на $unwindкод>
, но масивите, които се „развиват“, всъщност имат само един елемент в тях. Така че, моля, прости ми "Highlander"
препратки, на които не можах да устоя :)
db.users.aggregate([
// Match your document or documents
{ "$match": {
"commentUpvotes.id": 12
}},
// Get the one "up-votes" entry that matches
{ "$project": {
"posts": 1,
"comments": 1,
"commentUpVotes": {
"$setDifference": [
{
"$map": {
"input": "$commentUpvotes",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.id", 12 ] },
"$$el",
false
]
}
}
},
[false]
]
}
}},
// There is only one!
{ "$unwind": "$commentUpVotes" },
// Get the one comments entry that matches
{ "$project": {
"posts": 1,
"comments": {
"$setDifference": [
{
"$map": {
"input": "$comments",
"as": "el",
"in": {
"$cond": [
{
"$eq": [
{ "$substr": [ "$$el.id", 0, 4 ] },
"$commentUpVotes.commentId"
]
},
"$$el",
false
]
}
}
},
[false]
]
},
"commentUpVotes": 1
}},
// And there is only one!
{ "$unwind": "$comments" },
// Get the one post that matches
{ "$project": {
"posts": {
"$setDifference": [
{
"$map": {
"input": "$posts",
"as": "el",
"in": {
"$cond": [
{
"$eq": [
"$$el.id",
"$comments.postId"
]
},
"$$el",
false
]
}
}
},
[false]
]
},
"comments": 1,
"commentUpVotes": 1
}},
// Optionally group back to arrays. There can be only one!
{ "$group": {
"_id": "$_id",
"posts": { "$first": "$posts" },
"comments": { "$push": "$comments" },
"commentUpVotes": { "$push": "$commentUpVotes" }
}}
])
Така че крайният резултат ще бъде:
{
"_id" : ObjectId("539065d3cd0f2aac5f55778e"),
"posts" : [
{
"title" : "post1",
"id" : "123"
}
],
"comments" : [
{
"id" : 1910,
"postId" : "123",
"title" : "comment1",
"comment" : "some comment",
"user" : "user13"
}
],
"commentUpVotes" : [
{
"id" : 12,
"commentId" : "1910",
"upvotedBy" : "user91"
}
]
}
Знам, че поискахте „без промени в схемата“, но всъщност не е промяна в схемата, за да кажете, че е добра идея да запазите своя id
стойности тук от последователен тип. В момента смесвате цели числа и низове в този процес (надявам се, че е само пример), което не е добра идея.
По този начин има известно „ограничено кастинг“, което всъщност е налично, използвано тук с помощта на $substr
, но вашето действително решение може да варира в това как наистина да направите това. Горещо препоръчвам да коригирате данните, ако наистина се нуждаят от коригиране.
Във всеки случай, доста готина употреба за $ карта