web-dev-qa-db-fra.com

Comment rejoindre la requête dans mongodb?

J'ai une collection de documents utilisateur comme ceci:

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

Un utilisateur a beaucoup d'amis, j'ai la requête suivante en SQL:

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

J'aimerais avoir quelque chose de similaire dans MongoDB.

30
L.J.W

Edit: cette réponse ne s'applique qu'aux versions de MongoDb antérieures à la version 3.2.

Vous ne pouvez pas faire ce que vous voulez en une seule requête. Vous devez d'abord récupérer la liste des identifiants d'utilisateurs d'amis, puis les transmettre à la deuxième requête pour récupérer les documents et les trier par âge.

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

Pour avoir tout avec une seule requête en utilisant la fonctionnalité $ lookup de la structure d'agrégation, essayez ceci:

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

Disons que le contenu de votre collection d'utilisateurs est le suivant:

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

Le résultat de la requête sera:

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

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

Ceci est la documentation pour la requête de jointure dans mongodb, il s'agit d'une nouvelle fonctionnalité de la version 3.2.

Cela sera donc utile.

10
user3280472

MongoDB n'a pas de jointures, mais dans votre cas, vous pouvez faire: 

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

On dirait que personne n’a parlé de cette option d’utiliser Pivot en plus de MapReduce . Il existe un bon article qui pourrait être votre réponse ici http://cookbook.mongodb.org/patterns/pivot/ J'espère que cela vous aidera dans vos projets

2
Stephane Paquet

un type de jointure à une requête dans mongoDB, est de demander à une collection l’id qui correspond, de mettre les identifiants dans une liste (idlist) et de les utiliser avec une autre (ou la même) collection avec $ in: idlist

u = db.friends.find({"friends": ? }).toArray()
idlist= []
u.forEach(function(myDoc) { idlist.Push(myDoc.id ); } )
db.friends.find({"id": {$in : idlist} } )
1
Sérgio
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 } } ); 

ça marche pour moi.

0
Piyush Dholariya

Vous pouvez le faire en une fois en utilisant mongo-join-query . Voici à quoi cela ressemblerait:

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

Le résultat aura vos utilisateurs classés par âge et tous les objets amis incorporés.

Comment ça marche?

En coulisse, mongo-join-query utilisera votre schéma Mongoose pour déterminer les modèles à rejoindre et créera un pipeline d'agrégation qui effectuera la jointure et la requête.

0
Marcelo Lazaroni

Ne peupler que les amis du tableau.

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

Le résultat est le même comme ceci:

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

Idem: Mongoose - utilisation de Populate sur un tableau ObjectId

0
Mateus Pereira

Vous pouvez utiliser playOrm pour faire ce que vous voulez dans une requête (avec S-SQL Scalable SQL).

0
Dean Hiller