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.
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);
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
}
]
}
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.
MongoDB n'a pas de jointures, mais dans votre cas, vous pouvez faire:
db.coll.find({friends: userId}).sort({age: -1})
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
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} } )
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.
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.
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.
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
Vous pouvez utiliser playOrm pour faire ce que vous voulez dans une requête (avec S-SQL Scalable SQL).