web-dev-qa-db-ja.com

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でも同様のものが欲しいです。

35
L.J.W

編集:この回答は、v3.2より前のMongoDbのバージョンにのみ適用されます。

1つのクエリだけで目的の操作を行うことはできません。最初に友人のユーザーIDのリストを取得し、次にそれらのIDを2番目のクエリに渡してドキュメントを取得し、年齢で並べ替える必要があります。

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

集約フレームワークの$ lookup機能を使用して、すべてを1つのクエリで実行するには、次を試してください。

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

Userコレクションのコンテンツは次のとおりだとしましょう:

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

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

これはmongodbの結合クエリのドキュメントです。これはバージョン3.2の新機能です。

したがって、これは役に立ちます。

10
user3280472

MongoDBには結合はありませんが、あなたの場合は次のことができます:

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

mongoDBのクエリに参加する1つの種類は、1つのコレクションで一致するIDを要求し、IDをリスト(idlist)に入れ、他の(または同じ)コレクションで$ in:idlistを使用して検索します

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

わたしにはできる。

0

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スキーマを使用して、結合するモデルを決定し、結合とクエリを実行する 集約パイプライン を作成します。

0

アレイフレンドのみを設定します。

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-ObjectIdの配列でPopulateを使用

0
Mateus Pereira

PlayOrmを使用して、1つのクエリ(S-SQLスケーラブルSQL)で必要なことを実行できます。

0
Dean Hiller