sql >> データベース >  >> NoSQL >> MongoDB

MongoDBの$in句は順序を保証しますか

    前述のように、$ in句の配列内の引数の順序は、ドキュメントの取得方法の順序を反映していません。もちろん、それは自然な順序、または示されているように選択されたインデックスの順序になります。

    この順序を維持する必要がある場合は、基本的に2つのオプションがあります。

    したがって、_idの値を一致させていたとしましょう。 $inに渡される配列を含むドキュメント内 [ 4, 2, 8 ]として 。

    Aggregateを使用したアプローチ

    var list = [ 4, 2, 8 ];
    
    db.collection.aggregate([
    
        // Match the selected documents by "_id"
        { "$match": {
            "_id": { "$in": [ 4, 2, 8 ] },
        },
    
        // Project a "weight" to each document
        { "$project": {
            "weight": { "$cond": [
                { "$eq": [ "$_id", 4  ] },
                1,
                { "$cond": [
                    { "$eq": [ "$_id", 2 ] },
                    2,
                    3
                ]}
            ]}
        }},
    
        // Sort the results
        { "$sort": { "weight": 1 } }
    
    ])
    

    これが拡張フォームになります。ここで基本的に行われるのは、値の配列が$inに渡されるのと同じです。 また、「ネストされた」$condを作成します 値をテストし、適切な重みを割り当てるステートメント。その「重み」値は配列内の要素の順序を反映しているため、必要な順序で結果を取得するために、その値を並べ替えステージに渡すことができます。

    もちろん、実際には次のようにコードでパイプラインステートメントを「構築」します。

    var list = [ 4, 2, 8 ];
    
    var stack = [];
    
    for (var i = list.length - 1; i > 0; i--) {
    
        var rec = {
            "$cond": [
                { "$eq": [ "$_id", list[i-1] ] },
                i
            ]
        };
    
        if ( stack.length == 0 ) {
            rec["$cond"].push( i+1 );
        } else {
            var lval = stack.pop();
            rec["$cond"].push( lval );
        }
    
        stack.push( rec );
    
    }
    
    var pipeline = [
        { "$match": { "_id": { "$in": list } }},
        { "$project": { "weight": stack[0] }},
        { "$sort": { "weight": 1 } }
    ];
    
    db.collection.aggregate( pipeline );
    

    mapReduceを使用したアプローチ

    もちろん、それがすべてあなたの感性に重きを置いているように思われる場合は、mapReduceを使用して同じことを行うことができます。これは、見た目はシンプルですが、実行速度がやや遅くなる可能性があります。

    var list = [ 4, 2, 8 ];
    
    db.collection.mapReduce(
        function () {
            var order = inputs.indexOf(this._id);
            emit( order, { doc: this } );
        },
        function() {},
        { 
            "out": { "inline": 1 },
            "query": { "_id": { "$in": list } },
            "scope": { "inputs": list } ,
            "finalize": function (key, value) {
                return value.doc;
            }
        }
    )
    

    そして、それは基本的に、出力された「キー」値が入力配列でどのように発生するかという「インデックス順」にあることに依存しています。

    つまり、これらは基本的に、$inへの入力リストの順序を維持するための方法です。 そのリストが決まった順序ですでにある状態。



    1. Predisは「サーバーから行を読み取っているときにエラーが発生しました」

    2. REDISでキーの有効期限が切れたときにコールバックを取得する方法

    3. redisキャッシュが機能しているかどうかをテストするにはどうすればよいですか?

    4. 時間別のMongoDBグループ