Sub-Abfrage in MongoDB
Ich habe zwei collections in MongoDB, einer mit Nutzern und eine mit Aktionen. Die Benutzer sehen in etwa so:
{_id: ObjectId("xxxxx"), country: "UK",...}
und Aktionen wie
{_id: ObjectId("yyyyy"), createdAt: ISODate(), user: ObjectId("xxxxx"),...}
Ich versuche, Ereignisse zu zählen und verschiedene Benutzer aufgeteilt nach Land. Die erste Hälfte ist in Ordnung, aber wenn ich versuche, fügen Sie in einer sub-query zu ziehen, das Land erhalte ich nur null-Werte für Land
db.events.aggregate({
$match: {
createdAt: { $gte: ISODate("2013-01-01T00:00:00Z") },
user: { $exists: true }
}
},
{
$group: {
_id: {
year: { $year: "$createdAt" },
user_obj: "$user"
},
count: { $sum: 1 }
}
},
{
$group: {
_id: {
year: "$_id.year",
country: db.users.findOne({
_id: { $eq: "$_id.user_obj" },
country: { $exists: true }
}).country
},
total: { $sum: "$count" },
distinct: { $sum: 1 }
}
})
InformationsquelleAutor Youcef Kadri | 2015-07-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nicht mitkommt hier, nur uns trägt
Also MongoDB "nicht-Verknüpfungen". Sie haben möglicherweise versucht, so etwas wie dieses in der shell zum Beispiel:
Aber das macht nicht das was Sie scheinen zu denken, es tut. Es ist tatsächlich nicht genau, wie es aussieht und führt eine Abfrage auf die "Benutzer" - Kollektion für jedes Element, das zurückgegeben wird, aus dem "Ereignisse" - Kollektion, die sowohl "in und aus" den "client" und ist nicht auf dem server ausgeführt.
Für die gleichen Gründe, die Ihr 'embedded' - Anweisung innerhalb einer aggregation pipeline nicht wie das funktioniert. Im Gegensatz zu den oben genannten "die ganze pipeline" Logik an den server gesendet wird, bevor die Ausführung. Also, wenn du etwas getan hast, wie diese zu " wählen Sie "UK" Benutzer:
Dann, dass
.distinct()
Abfrage tatsächlich ausgewertet, auf dem "client" und nicht auf dem server und daher nicht mit Verfügbarkeit zu jedem Dokument Werte in der aggregation pipeline. Also die.distinct()
zuerst ausgeführt wird, gibt es das array als argument und dann die ganze pipeline an den server gesendet wird. Das ist die Reihenfolge der Ausführung.Korrektur
Müssen Sie mindestens ein gewisses Maß an de-Normalisierung für die Art der Abfrage, die Sie ausführen möchten, um zu arbeiten. So haben Sie in der Regel zwei Möglichkeiten:
Einbetten der ganze user-Objekt-Daten in die event-Daten.
Mindestens einbetten "einige" der Benutzer-Objekt-Daten in die event-Daten. In diesem Fall "Land", weil du gehst, es zu benutzen.
Also dann, wenn Sie Folgen Sie der "zweiten" Falle und mindestens "verlängern" Sie Ihre vorhandenen Daten ein wenig "Land" wie folgt:
Dann die "aggregation" Prozess wird einfach:
Wir sind nicht normal
Fixieren Sie Ihre Daten, um die Informationen, die es braucht auf einer einzigen Sammlung, wo wir "das nicht tun verbindet" ist ein relativ einfaches Verfahren. Wirklich nur eine Variante der ursprünglichen Abfrage-Beispiel oben:
Also das ist, was es überhaupt geht. Einzelne Abfragen zu einer MongoDB-server erhalten "Sammlung" und "Sammlung nur" mit zu arbeiten. Auch das fantastische "Bulk-Vorgänge", wie oben gezeigt, kann immer noch nur "gestapelt" auf einem einzigen Sammlung.
Wenn Sie wollen, Dinge zu tun wie "Aggregat auf Verwandte Eigenschaften", dann "muss" enthalten, die die Eigenschaften, die in der Sammlung sind Sie der Aggregation von Daten. Es ist vollkommen in Ordnung, live mit den Daten sitzen in getrennten Sammlungen, wie zum Beispiel "Benutzer" würde in der Regel mehr Informationen beigefügt, um Sie als einfach und "_id" und "Land".
Aber der Punkt hier ist, wenn Sie "Land" für die Analyse der "Ereignis" - Daten, indem Sie "Benutzer", dann gehören Sie in den Daten als gut. Die effizientesten server join ist ein "vor-sich", das ist die Theorie in der Praxis im Allgemeinen.
InformationsquelleAutor Blakes Seven