In Anbetracht der "Einrückung", die ich in der Auflistung verwende, kann dies tatsächlich länger aussehen als das, was Sie tun, aber das ist es wirklich nicht.
Dies ist ein weiteres wirklich gutes Beispiel für die Verwendung von $ Karte
wie für MongoDB 2.6 und höher verfügbar. Es wird immer noch $unwind
, aber die Arrays, die "abgewickelt" werden, haben eigentlich immer nur eines Element in ihnen. Verzeihen Sie also bitte meinen "Highlander"
Referenzen, denen ich nicht widerstehen konnte :)
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" }
}}
])
Das Endergebnis wäre also:
{
"_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"
}
]
}
Ich weiß, dass Sie nach "keine Schemaänderungen" gefragt haben, aber nicht wirklich eine Schemaänderung, um zu sagen, dass es eine gute Idee ist, Ihre id
beizubehalten Werte hier von einem konsistenten Typ. Momentan mischen Sie Integers und Strings in diesem Prozess (ich hoffe, es ist nur ein Beispiel), was keine gute Idee ist.
Daher gibt es einige "eingeschränkte Übertragungen", die hier tatsächlich verfügbar sind, unter Verwendung von $substr
, Ihre tatsächliche Lösung kann jedoch davon abweichen, wie Sie dies wirklich tun. Ich empfehle dringend, die Daten zu reparieren, wenn sie wirklich repariert werden müssen.
Auf jeden Fall eine ziemlich coole Verwendung für $ Karte