MongoDB wyszukuje wiele kolekcji naraz
users
{
"_id":"12345",
"admin":1
},
{
"_id":"123456789",
"admin":0
}
posts
{
"content":"Some content",
"owner_id":"12345",
"via":"facebook"
},
{
"content":"Some other content",
"owner_id":"123456789",
"via":"facebook"
}
Oto próbka z mojego mongodb. Chcę uzyskać wszystkie posty, które mają atrybut" via "równy" facebook " i wysłany przez admina ("admin": 1). Nie mogłem wymyślić, jak zdobyć to zapytanie. Ponieważ mongodb nie jest relacyjną bazą danych, nie mogłem wykonać operacji join. Jakie może być rozwiązanie ? 6 answers
Próba przyłączenia się do MongoDB nie udałoby się użyć MongoDB. Możesz jednak użyć DBref i napisać kod (lub bibliotekę) na poziomie aplikacji, aby automatycznie pobierał te odniesienia dla Ciebie.
LUB możesz zmienić swój schemat i użyć wbudowanych dokumentów .
Twoim ostatecznym wyborem jest zostawić rzeczy dokładnie takie, jakie są teraz i zrobić dwa zapytania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-28 07:02:17
Możesz użyć $lookup
(multiple), aby pobrać rekordy z wielu kolekcji:
Przykład:
Jeśli masz więcej kolekcji (ja mam 3 kolekcje na demo tutaj, możesz mieć więcej niż 3 ). i chcę pobrać dane z 3 kolekcji w jednym obiekcie:
Kolekcja to as:
Db.doc1.find().pretty();
{
"_id" : ObjectId("5901a4c63541b7d5d3293766"),
"firstName" : "shubham",
"lastName" : "verma"
}
Db.doc2.find().pretty();
{
"_id" : ObjectId("5901a5f83541b7d5d3293768"),
"userId" : ObjectId("5901a4c63541b7d5d3293766"),
"address" : "Gurgaon",
"mob" : "9876543211"
}
Db.doc3.find().pretty();
{
"_id" : ObjectId("5901b0f6d318b072ceea44fb"),
"userId" : ObjectId("5901a4c63541b7d5d3293766"),
"fbURLs" : "http://www.facebook.com",
"twitterURLs" : "http://www.twitter.com"
}
Teraz Twoje zapytanie będzie następujące:
db.doc1.aggregate([
{ $match: { _id: ObjectId("5901a4c63541b7d5d3293766") } },
{
$lookup:
{
from: "doc2",
localField: "_id",
foreignField: "userId",
as: "address"
}
},
{
$unwind: "$address"
},
{
$project: {
__v: 0,
"address.__v": 0,
"address._id": 0,
"address.userId": 0,
"address.mob": 0
}
},
{
$lookup:
{
from: "doc3",
localField: "_id",
foreignField: "userId",
as: "social"
}
},
{
$unwind: "$social"
},
{
$project: {
__v: 0,
"social.__v": 0,
"social._id": 0,
"social.userId": 0
}
}
]).pretty();
Wtedy twój wynik będzie:
{
"_id" : ObjectId("5901a4c63541b7d5d3293766"),
"firstName" : "shubham",
"lastName" : "verma",
"address" : {
"address" : "Gurgaon"
},
"social" : {
"fbURLs" : "http://www.facebook.com",
"twitterURLs" : "http://www.twitter.com"
}
}
Jeśli chcesz wszystkie rekordy z każdej kolekcji, powinieneś usunąć poniższy wiersz z zapytania:
{
$project: {
__v: 0,
"address.__v": 0,
"address._id": 0,
"address.userId": 0,
"address.mob": 0
}
}
{
$project: {
"social.__v": 0,
"social._id": 0,
"social.userId": 0
}
}
Po usunięciu powyższego kodu otrzymasz całkowity rekord as:
{
"_id" : ObjectId("5901a4c63541b7d5d3293766"),
"firstName" : "shubham",
"lastName" : "verma",
"address" : {
"_id" : ObjectId("5901a5f83541b7d5d3293768"),
"userId" : ObjectId("5901a4c63541b7d5d3293766"),
"address" : "Gurgaon",
"mob" : "9876543211"
},
"social" : {
"_id" : ObjectId("5901b0f6d318b072ceea44fb"),
"userId" : ObjectId("5901a4c63541b7d5d3293766"),
"fbURLs" : "http://www.facebook.com",
"twitterURLs" : "http://www.twitter.com"
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-27 09:20:36
Oto odpowiedź na twoje pytanie.
db.getCollection('users').aggregate([
{$match : {admin : 1}},
{$lookup: {from: "posts",localField: "_id",foreignField: "owner_id",as: "posts"}},
{$project : {
posts : { $filter : {input : "$posts" , as : "post", cond : { $eq : ['$$post.via' , 'facebook'] } } },
admin : 1
}}
])
Albo możesz wybrać opcję grupy mongodb.
db.getCollection('users').aggregate([
{$match : {admin : 1}},
{$lookup: {from: "posts",localField: "_id",foreignField: "owner_id",as: "posts"}},
{$unwind : "$posts"},
{$match : {"posts.via":"facebook"}},
{ $group : {
_id : "$_id",
posts : {$push : "$posts"}
}}
])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-01 15:29:39
Jak wspomniano wcześniej w MongoDB, nie można łączyć kolekcji.
Dla Twojego przykładu rozwiązaniem może być:
var myCursor = db.users.find({admin:1});
var user_id = myCursor.hasNext() ? myCursor.next() : null;
db.posts.find({owner_id : user_id._id});
Zobacz sekcję podręczniki referencyjne - Kursory: http://es.docs.mongodb.org/manual/core/cursors/
Innym rozwiązaniem byłoby osadzenie użytkowników w kolekcji postów, ale myślę, że dla większości aplikacji internetowych zbiór użytkowników musi być niezależny ze względów bezpieczeństwa. Zbiór użytkowników może mieć role, zezwolenia itp.
posts
{
"content":"Some content",
"user":{"_id":"12345", "admin":1},
"via":"facebook"
},
{
"content":"Some other content",
"user":{"_id":"123456789", "admin":0},
"via":"facebook"
}
Oraz wtedy:
db.posts.find({user.admin: 1 });
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 12:57:56
Wykonaj wiele zapytań lub użyj osadzonych dokumentów lub spójrz na "odniesienia do bazy danych".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-28 06:53:04
Jedno rozwiązanie: dodaj flagę isAdmin: 0/1 do dokumentu kolekcji postów.
Inne rozwiązanie: użyj DBrefs
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-28 06:53:36