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

推荐答案

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

如果你需要保持这种秩序,那么你基本上有两个 Select .

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

使用聚合的方法


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的方法,在这种情况下,您已经以确定的顺序拥有了该列表.

Mongodb相关问答推荐

MongoDB:用特殊字符创建的drop collection

MongoDB聚合匹配字符串字符

为什么AllowDiskUse不能在$GROUP阶段的聚合管道中工作?

我们可以在Mongoose中这样使用Unique:[True,";This to Unique&qot;]吗

在MondoDB中:将对象数组从切片索引数组切片,并通过聚合推入数组

如何在Mongo中制作全覆盖索引

无法配置数据源:未指定url属性,无法为 MongoDb 配置嵌入数据源

MongoDB - 家庭作业(job)帮助.不确定如何在 mongodb 中访问文档中的变量

Mongodb聚合中基于其他字段值的多个条件的动态新字段值

mongo.lock 文件有什么用?

Meteor mongo 驱动程序可以处理 $each 和 $position 运算符吗?

如何使用 Spring Data MongoDB 通过 GridFS ObjectId 获取二进制流

如何在 MongoDb 中进行类似于嵌套 Sql Select 查询的嵌套查询

使用 MongoDB 更新数组字段内的特定键/值

如何知道 MongoDB 集合大小?

如何获取 Mongoid 文档的所有字段名称?

了解 Mongoose 中的关系和外键

MongoDB 按数组元素对文档进行排序

无法在 mac os 10.9 上安装 mongodb php 驱动程序

MongoDB InsertMany 与 BulkWrite