MongoDB запрашивает несколько коллекций одновременно - PullRequest
60 голосов
/ 28 июня 2011
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"
}

Вот пример с моего mongodb.Я хочу получить все сообщения, которые имеют атрибут "via", равный "facebook" и опубликованные администратором ("admin": 1)Я не мог понять, как получить этот запрос.Поскольку mongodb не является реляционной базой данных, я не смог выполнить операцию соединения.Какое может быть решение?

Ответы [ 7 ]

44 голосов
/ 28 июня 2011

Попытка ПРИСОЕДИНИТЬСЯ к MongoDB потеряет цель использования MongoDB. Однако вы можете использовать DBref и написать свой код (или библиотеку) уровня приложения, чтобы он автоматически выбирал эти ссылки для вас.

Или вы можете изменить свою схему и использовать встроенные документы .

Ваш окончательный выбор - оставить все как есть и выполнить два запроса.

17 голосов
/ 22 октября 2016

Вот ответ на ваш вопрос.

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

        }}

])

Или вы можете выбрать вариант группы 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"}
    }}
])
13 голосов
/ 27 апреля 2017

Вы можете использовать $lookup (несколько) для получения записей из нескольких коллекций:

Пример:

Если у вас есть больше коллекций (у меня есть 3 коллекции)для демонстрации здесь вы можете иметь более 3).и я хочу получить данные из 3 коллекций в одном объекте:

Коллекция имеет вид:

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"
}

Теперь ваш запрос будет выглядеть следующим образом:

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();

Тогда Ваш результат будет:

{
    "_id" : ObjectId("5901a4c63541b7d5d3293766"),
    "firstName" : "shubham",
    "lastName" : "verma",

    "address" : {
        "address" : "Gurgaon"
    },
    "social" : {
        "fbURLs" : "http://www.facebook.com",
        "twitterURLs" : "http://www.twitter.com"
    }
}

Если вы хотите, чтобы все записи из каждой коллекции были удалены из строки ниже:

{
            $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
           }
     }

После удаления вышекод вы получите общую запись как:

{
    "_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"
    }
}
8 голосов
/ 13 ноября 2013

Как упоминалось ранее в MongoDB, вы не можете объединяться между коллекциями.

Для вашего примера решение может быть:

var myCursor = db.users.find({admin:1});
var user_id = myCursor.hasNext() ? myCursor.next() : null;
db.posts.find({owner_id : user_id._id});

См. Справочное руководство - раздел курсоров: http://es.docs.mongodb.org/manual/core/cursors/

Другим решением было бы включение пользователей в коллекцию сообщений, но я думаю, что для большинства веб-приложений коллекция пользователей должна быть независимой по соображениям безопасности.Коллекция пользователей может иметь роли, разрешения и т. Д.

posts
{
 "content":"Some content",
 "user":{"_id":"12345", "admin":1},
 "via":"facebook"
},
{
 "content":"Some other content",
 "user":{"_id":"123456789", "admin":0},
 "via":"facebook"
}

, а затем:

db.posts.find({user.admin: 1 });
3 голосов
/ 28 июня 2011

Выполните несколько запросов или используйте встроенные документы или посмотрите «ссылки на базу данных».

2 голосов
/ 28 июня 2011

Одно решение: добавьте isAdmin: флаг 0/1 к вашему документу коллекции постов.

Другое решение: используйте DBrefs

1 голос
/ 20 января 2016

Вы можете написать пример JavaScript, как показано ниже, и вызывать функцию при необходимости.

См. Иллюстрацию по адресу: http://dbversity.com/mongodb-querying-multiple-collections-with-a-javascript/

function colListQuery() {
var tcol = new Array()
tcol= db.getCollectionNames();
for(var i = 1; i < tcol.length ; i++) {
query = “db.” + tcol[i] + “.find()”;

var docs= eval(query);
docs.forEach( function(doc, index){ print( “Database_Name:”, db, “Collection_Name:”, tcol[i], “x_value:”, doc.x, “_id:”, doc._id) });

}
}

Затем вызовите его с помощью colListQuery ()вам это нужно, как показано на иллюстрации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...