web-dev-qa-db-ja.com

ネストされたSQL選択クエリのように機能するMongoDbでネストされたクエリを作成する方法

MongoDbで効率的なクエリを実行して、ユーザーグループにユーザーIDがリストされているすべてのユーザーを検索したいと思います。理想的には、これをMongodbへの単一のリクエストとして作成したいと思います。私が欲しいのはSQLのネストされたselectに対応します。私はこれをmongoシェルで試しました:

db.user.save({_id:"u1", Name:"u1 name"});
db.user.save({_id:"u2", Name:"u1 name"});
db.user.save({_id:"u3", Name:"u3 name"});
db.usergroup.save({_id:"g1", Users: ["u2","u3"]});

これが私がやりたい選択ですが、["u2"、 "u3"]配列をハードコーディングせずに:

db.user.find({_id:{$in:["u2","u3"]}}).forEach(printjson);

これは正常に機能し、u2とu3のユーザーオブジェクトを返します。

ここで問題となるのは、クエリで抽出された$ in演算子のユーザーIDの配列を取得して、クエリ全体を1回のリクエストで実行できるようにする方法です。

このような「ネストされたクエリ」は機能しません。

db.user.find({_id:{$in:db.usergroup.find({_id:"g1"},{_id:0,Users:1})}}).forEach(printjson);

このエラーが発生します:Tue Mar 27 06:17:41キャッチされない例外:エラー:{"$ err": "invalid query"、 "code":12580}の読み込みに失敗しました:mongoNestedSelect.js

1)これはmongodbで可能ですか?

2)公式のc#ドライバーでこれを行う方法は?

14
ssn

MongoDBでのこのような質問に対する答えは、多くの場合、データを非正規化することです。グループ内のユーザーのリストだけが必要な場合は、ユーザーID andユーザー名をグループドキュメントに保存できます。いくつかの方法では、データベースを正規化された形式に配置しようとするのではなく、画面に表示したい結果に従ってデータベースを構造化します。

明らかに、これは(名前付きの)ユーザーグループリストが単一のドキュメントに収まる場合にのみ機能しますが、現在のアプローチには、グループの最大サイズに関してもいくつかの制限があります。

別のアプローチは、ユーザーが属するグループを各「ユーザー」ドキュメントの配列に格納することです。その配列フィールドにインデックスを追加すると、グループごとにユーザーを見つけることができます。ユーザーがグループ内のメンバーよりも少ないグループに属する可能性が高いことを考えると、これがここでの最良のアプローチである可能性があります。

db.user.save({_id:"u1", name:"u1 name", groups:[{_id:"g1", name:"Group One"}, ...]});

ここでも、グループ名を_idとともに保存して、ユーザーが属するグループのリストを1回の往復ですぐに表示できるようにすることができます。もちろん、グループ名の変更を許可する場合は、バックグラウンドタスクを開始して、名前のこれらすべてのコピーを修正する必要があります。

また、独自のMongoDB IDジェネレーターではなく、組み込みのMongoDB IDジェネレーターを使用します。これには、多くの望ましいプロパティがあります。

7
Ian Mercer

関数の定義

function bbb(){
    var org_ids = new Array();
    var orgs = 
        db.orgTreeNode.find({ancestors:"ca5cd344-ba47-4601-a07b-ea2c684bfb4e"},{"_id":1});
    orgs.forEach(function(org){
        org_ids.Push(org._id);
    })

    return db.user.find({"org":{$in:org_ids}}).skip(300).limit(10);
}

実行機能

bbb()
7
pippo

それがあなたに答えを得るきっかけになることができれば-

db.users.find({
    _id: {
        $in: db.logs.find({
            loggedbyuser: {
                $ne: ObjectId("569f9d093447ee781ca80b52")
            },
            logtype: "marketfetched",
            "logcreated": {
                $gt: new ISODate("2016-02-06T00:00:00.871Z")
            }
        }, {
            loggedbyuser: 1,
            _id: 0
        }).sort({
            'logcreated': -1
        }).map(function(like) {
            return like.loggedbyuser;
        })
    }
}).map(function(like) {
    return like.fullname;
});
1
Markrings

-sUReN

SQLクエリ:(グループ化と個別のカウント)

select city,count(distinct(emailId)) from TransactionDetails group by city;

同等のmongoクエリは次のようになります:

db.TransactionDetails.aggregate([ 
{$group:{_id:{"CITY" : "$cityName"},uniqueCount: {$addToSet: "$emailId"}}},
{$project:{"CITY":1,uniqueCustomerCount:{$size:"$uniqueCount"}} } 
]);

私はmongodbのネストされたクエリについて同じことを考えていました。私の場合、私は少しパッツしてそれを機能させました、そしてあなたも「$ or」を使用してtoArray()を使用することでそうなると思います

db.user.find({$or:db.usergroup.find({_id:"g1"},{_id:0,Users:1}).toArray()})

正しくないかもしれませんが、これは次のクエリを使用して機能した私のデータの例です。この場合、IDを別のクエリにフィードバックする理由としては明らかに少しばかげていますが、それが機能するかどうかを確認したいと思っていました。

db.notification.find({$or:db.notification.find({'startDate': { '$gte': ISODate("2019-08-01") }},{_id:1}).limit(10).toArray()})
0
Starlton