Подтвердить что ты не робот

Как присоединиться к запросу в mongodb?

У меня есть коллекция документов пользователя, как это:

User {
   id:"001"
   name:"John",
   age:30,
   friends:["userId1","userId2","userId3"....]
}

У пользователя много друзей, у меня следующий запрос в SQL:

select * from user where in (select friends from user where id=?) order by age

Я хотел бы иметь что-то подобное в MongoDB.

4b9b3361

Ответ 1

Изменение: этот ответ относится только к версиям MongoDb до v3.2.

Вы не можете делать то, что вы хотите, всего за один запрос. Сначала вам нужно получить список идентификаторов друзей, а затем передать эти идентификаторы во второй запрос, чтобы получить документы и отсортировать их по возрасту.

var user = db.user.findOne({"id" : "001"}, {"friends": 1})
db.user.find( {"id" : {$in : user.friends }}).sort("age" : 1);

Ответ 2

Чтобы иметь всего лишь один запрос, используя функцию $lookup в структуре агрегации, попробуйте следующее:

db.User.aggregate(
    [
        // First step is to extract the "friends" field to work with the values
        {
            $unwind: "$friends"
        },
        // Lookup all the linked friends from the User collection
        {
            $lookup:
            {
                from: "User",
                localField: "friends",
                foreignField: "_id",
                as: "friendsData"
            }
        },
        // Sort the results by age
        {
            $sort: { 'friendsData.age': 1 }
        },
        // Get the results into a single array
        {
            $unwind: "$friendsData"
        },
        // Group the friends by user id
        {
            $group:
            {
                _id: "$_id",
                friends: { $push: "$friends" },
                friendsData: { $push: "$friendsData" }
            }
        }
    ]
)

Скажем, содержимое вашей пользовательской коллекции выглядит следующим образом:

{
    "_id" : ObjectId("573b09e6322304d5e7c6256e"),
    "name" : "John",
    "age" : 30,
    "friends" : [
        "userId1",
        "userId2",
        "userId3"
    ]
}
{ "_id" : "userId1", "name" : "Derek", "age" : 34 }
{ "_id" : "userId2", "name" : "Homer", "age" : 44 }
{ "_id" : "userId3", "name" : "Bobby", "age" : 12 }

Результатом запроса будет:

{
    "_id" : ObjectId("573b09e6322304d5e7c6256e"),
    "friends" : [
        "userId3",
        "userId1",
        "userId2"
    ],
    "friendsData" : [
        {
            "_id" : "userId3",
            "name" : "Bobby",
            "age" : 12
        },
        {
            "_id" : "userId1",
            "name" : "Derek",
            "age" : 34
        },
        {
            "_id" : "userId2",
            "name" : "Homer",
            "age" : 44
        }
    ]
}

Ответ 4

MongoDB не имеет объединений, но в вашем случае вы можете сделать:

db.coll.find({friends: userId}).sort({age: -1})

Ответ 5

Похоже, никто не говорил об этом варианте использования Pivot в добавлении к MapReduce. Есть хорошая статья, которая может быть вашим ответом здесь http://cookbook.mongodb.org/patterns/pivot/ Надеюсь, это поможет вам в ваших проектах.

Ответ 6

один вид соединения запроса в mongoDB, запрашивается в одной коллекции для идентификатора, который соответствует, помещает идентификаторы в список (список idlist) и находит использование в другой (или такой же) коллекции с помощью $in: idlist

u = db.friends.find({"friends": ? }).toArray()
idlist= []
u.forEach(function(myDoc) { idlist.push(myDoc.id ); } )
db.friends.find({"id": {$in : idlist} } )

Ответ 7

Вы можете использовать playOrm, чтобы делать то, что вы хотите, в одном запросе (с S-SQL масштабируемым SQL).

Ответ 8

var p = db.sample1.find().limit(2) , 
    h = [];
for (var i = 0; i < p.length(); i++) 
{
  h.push(p[i]['name']);
}
db.sample2.find( { 'doc_name': { $in : h } } ); 

он работает для меня.

Ответ 9

Вы можете сделать это за один раз, используя mongo-join-query. Вот как это будет выглядеть:

const joinQuery = require("mongo-join-query");

joinQuery(
    mongoose.models.User,
    {
        find: {},
        populate: ["friends"],
        sort: { age: 1 },
    },
    (err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
);

В результате пользователи будут упорядочены по возрасту и всем встроенным объектам друзей.

Как это работает?

За кулисами mongo-join-query будет использоваться ваша схема Mongoose, чтобы определить, к каким моделям присоединиться, и создаст конвейер агрегации , который будет выполнять join и запрос.

Ответ 10

Только заполнить массив друзей.

User.findOne({ _id: "userId"})
.populate('friends')
.exec((err, user) => {
    //do something
});

Результат такой же, как этот:

{
    "_id" : "userId",
    "name" : "John",
    "age" : 30,
    "friends" : [
        { "_id" : "userId1", "name" : "Derek", "age" : 34 }
        { "_id" : "userId2", "name" : "Homer", "age" : 44 }
        { "_id" : "userId3", "name" : "Bobby", "age" : 12 }
    ]
}

То же самое: Mongoose - использование Populate для массива ObjectId