Jak dołączyć do zapytania w mongodb?

Mam taką kolekcję dokumentów użytkownika:

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

Użytkownik ma wielu znajomych, mam następujące zapytanie w SQL:

select * from user where in (select friends from user where id=?) order by age
Chciałbym mieć coś podobnego w MongoDB.
Author: Adarsh Ravi, 2010-12-30

10 answers

Edit: ta odpowiedź dotyczy tylko wersji MongoDb przed v3. 2.

Nie możesz zrobić tego, co chcesz w jednym zapytaniu. Najpierw należy pobrać listę identyfikatorów znajomych, a następnie przekazać je do drugiego zapytania, aby pobrać dokumenty i posortować je według wieku.

var user = db.user.findOne({"id" : "001"}, {"friends": 1})
db.user.find( {"id" : {$in : user.friends }}).sort("age" : 1);
 33
Author: dannie.f,
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
2019-01-30 17:59:28

Aby mieć wszystko za pomocą jednego zapytania używając funkcji $ lookup frameworku agregacji, spróbuj tego :

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

Załóżmy, że zawartość twojej kolekcji użytkowników jest następująca:

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

Wynik zapytania będzie następujący:

{
    "_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
        }
    ]
}
 38
Author: Derek,
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-05-17 12:59:17

Https://docs.mongodb.org/manual/reference/operator/aggregation/lookup/

To jest dokument dla zapytania join w mongodb , jest to nowa funkcja od wersji 3.2.

Więc to będzie pomocne.

 11
Author: user3280472,
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-01-25 19:04:38

MongoDB nie ma joinów, ale w Twoim przypadku możesz to zrobić:

db.coll.find({friends: userId}).sort({age: -1})
 5
Author: pingw33n,
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
2010-12-30 14:46:09

Możesz używać w Moongoose JS .populate() i { populate : { path : 'field' } }. Przykład:

Modele:

 mongoose.model('users', new Schema({
        name:String,
        status: true,
        friends: [{type: Schema.Types.ObjectId, ref:'users'}], 
        posts: [{type: Schema.Types.ObjectId, ref:'posts'}], 

    }));
 mongoose.model('posts', new Schema({
            description: String,
            comments: [{type: Schema.Types.ObjectId, ref:'comments'}], 

        }));
 mongoose.model('comments', new Schema({
            comment:String,
            status: true

        }));

Jeśli chcesz zobaczyć posty swoich znajomych, możesz użyć tego.

Users.find().                    //Collection 1
        populate({path:'friends',   //Collection 2
        populate:{path:'posts'   //Collection 3
        }})
    .exec();

Jeśli chcesz zobaczyć posty swoich znajomych, a także przynieść wszystkie komentarze, możesz użyć tego i też, możesz zidentyfikować kolekcję, jeśli nie znajdziesz I zapytanie jest błędne.

 Users.find().                                    //Collection 1
        populate({path:'friends',                 //Collection 2
        populate:{path:'posts',                   //Collection 3
        populate:{path:'commets, model:Collection'//Collection 4 and more
        }}})
    .exec();

I na koniec, jeśli chcesz uzyskać tylko niektóre pola z jakiejś kolekcji, możesz użyć propiertie select Example:

Users.find().                                    
        populate({path:'friends', select:'name status friends'                  
        populate:{path:'comments'               
        }})
    .exec();
 4
Author: Andrey Araya,
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
2020-05-27 06:44:54

Jednym z rodzajów dołączania do zapytania w mongoDB jest zapytanie w jednej kolekcji o id , które pasują, umieszczanie ID na liście (idlist) i znajdowanie w innej (lub tej samej) kolekcji za pomocą $in : idlist

u = db.friends.find({"friends": ? }).toArray()
idlist= []
u.forEach(function(myDoc) { idlist.push(myDoc.id ); } )
db.friends.find({"id": {$in : idlist} } )
 2
Author: Sérgio,
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
2014-10-20 03:55:28

/ Align = "left" /

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

Wynik jest taki sam:

{
    "_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 }
    ]
}

To samo: Mongoose - za pomocą wypełnienia na tablicy ObjectId

 1
Author: Mateus Pereira,
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
2018-07-23 19:56:31

Możesz użyć playOrm, aby zrobić to, co chcesz w jednym zapytaniu (z S-SQL skalowalny SQL).

 0
Author: Dean Hiller,
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
2012-09-07 17:31:48
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 } } ); 
U mnie działa.
 0
Author: Piyush Dholariya,
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
2014-11-28 07:52:27

Możesz to zrobić za jednym razem używając mongo-join-query. Oto jak by to wyglądało:

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

Wynik spowoduje uporządkowanie użytkowników według wieku i osadzenie wszystkich obiektów znajomych.

Jak to działa?

Behind the scenes mongo-join-query użyje schematu Mongoose do określenia, które modele należy połączyć i utworzy rurociąg agregacji, który wykona połączenie i zapytanie.

 0
Author: Marcelo Lazaroni,
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-12-13 14:36:55