MongoDB 的 $in 子句是否保证顺序 [英] Does MongoDB's $in clause guarantee order

查看:102
本文介绍了MongoDB 的 $in 子句是否保证顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When using MongoDB's $in clause, does the order of the returned documents always correspond to the order of the array argument?

推荐答案

如前所述,$in 子句数组中参数的顺序并不反映文档的检索顺序.那当然是自然顺序或如图所示的选定索引顺序.

As noted, the order of the arguments in the array of an $in clause does not reflect the order of how the documents are retrieved. That of course will be the natural order or by the selected index order as shown.

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

If you need to preserve this order, then you basically have two options.

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

So let's say that you were matching on the values of _id in your documents with an array that is going to be passed in to the $in as [ 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 语句来测试值并分配适当的权重.由于权重"值反映了数组中元素的顺序,因此您可以将该值传递给排序阶段,以便按所需顺序获得结果.

So that would be the expanded form. What basically happens here is that just as the array of values is passed to $in you also construct a "nested" $cond statement to test the values and assign an appropriate weight. As that "weight" value reflects the order of the elements in the array, you can then pass that value to a sort stage in order to get your results in the required order.

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

Of course you actually "build" the pipeline statement in code, much like this:

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 做同样的事情,它看起来更简单,但运行速度可能会稍慢一些.

Approach using mapReduce


Of course if that all seems to hefty for your sensibilities then you can do the same thing using mapReduce, which looks simpler but will likely run somewhat slower.

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;
        }
    }
)

这基本上依赖于发出的键"值在输入数组中出现的索引顺序".

And that basically relies on the emitted "key" values being in the "index order" of how they occur in the input array.

因此,这些基本上是您将输入列表的顺序维护到 $in 条件的方法,其中您已经以确定的顺序拥有该列表.

So those essentially are your ways of maintaining the order of a an input list to an $in condition where you already have that list in a determined order.

这篇关于MongoDB 的 $in 子句是否保证顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆