mongodb - MongoDB 的 $in 子句是否保证顺序

使用 MongoDB 的 $in 时子句,返回文档的顺序是否总是与数组参数的顺序相对应?

最佳答案

如前所述,$in 子句数组中参数的顺序并不反射(reflect)文档检索的顺序。这当然是自然顺序或如图所示的所选索引顺序。

如果你需要保留这个顺序,那么你基本上有两种选择。

假设您在文档中将 _id 的值与将作为 传递给 $in 的数组进行匹配[ 4, 2, 8 ].

使用聚合的方法


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 语句来测试值并分配适当的权重.由于该“权重”值反射(reflect)了数组中元素的顺序,因此您可以将该值传递给排序阶段,以便按所需顺序获得结果。

当然,您实际上是在代码中“构建”管道语句,就像这样:

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 条件的方法,在该条件下,您已经以确定的顺序拥有该列表。

https://stackoverflow.com/questions/22797768/

相关文章:

python - MongoKit vs MongoEngine vs Flask-MongoAlc

node.js - Mongoose,更新对象数组中的值

mongodb - 如何在mongodb中查询子对象

mongodb - MongoDB 中的 $unwind 运算符是什么?

mongodb - 在 Mongo 中,我如何漂亮地打印结果,所以 .find() 看起来像 .fi

javascript - 使用 Node.js 和 MongoDB 存储密码

node.js - 在 OSX 上安装和运行 MongoDB

mongodb - 在 MongoDB 中是否有命名集合的约定?

javascript - 如何使用 node.js 连接到 mongodb(并进行身份验证)?

mongodb - MongoDB中的数据重复太多?