对 MongoDB $in 查询的响应顺序? [复制]

Posted

技术标签:

【中文标题】对 MongoDB $in 查询的响应顺序? [复制]【英文标题】:Order of responses to MongoDB $in query? [duplicate] 【发布时间】:2011-03-09 16:58:54 【问题描述】:

$in 条件运算符上的 MongoDB 文档没有说明任何关于顺序的内容。如果我运行表单查询

db.things.find('_id': '$in': id_array);

返回结果的顺序是什么?有没有办法告诉 MongoDB “我希望对结果进行排序,以便它们与 id_array 中的 id 的顺序相同?”

【问题讨论】:

2.6 的任何解决方案? 简单的 Python/PyMongo 解决方案:***.com/a/40048951/304209 检查this 答案。 【参考方案1】:

在JIRA 上请求此功能:

很快就得到了很好的回应:用$or代替$in

c.find(  _id: $in:[ 1, 2, 0 ]   ).toArray()

对比

c.find(  $or:[  _id:1 ,  _id:2 ,  _id:0  ]  ).toArray()

阅读错误报告了解更多信息。

更新

$or work-around hack 从 2.6.x 开始不再有效 - 这是实现的副作用,具有 changed。

【讨论】:

当您以编程方式生成列表时并不那么容易/好,但有一个解决方案很好。 此方法似乎不适用于 2.6.x,如 JIRA 评论中所述【参考方案2】:

如果您不介意使用 Underscore.js 并且不太担心规模(IE,您不介意 fetch-ing 而不是使用光标),以下是我维持秩序的方式:

var results = db.things.find('_id': '$in': id_array).fetch(); 
return _.sortBy(results, function(thing)  
  return id_array.indexOf(thing._id); 
);

【讨论】:

我在这里看到了一个权衡:这种方法看起来更干净,但它可能会使用更多的 CPU。发生这种情况是因为 array.indexOf 将为您的结果数组中的每个项目扫描 id_array ,并且在完成所有这些工作之后,它会结束对所有结果的处理。自己检查一下:jsfiddle.net/davidrc/gyjrtovu 当然这对前端来说不是问题(我们正在谈论一些毫秒),但是当我们在后端运行此代码时,可能会增加额外的负载。 同意。我必须为 【参考方案3】:

@Jason 的答案是正确的。

关于其他答案:我不建议一一查询,因为它会带来严重的性能问题。

除了@Jason 的回答,还可以使用 Array.reduce 和 Array.map 方法进行优化,像这样:

//The order you want
var queryIds = [8, 5, 3, 7];

//The results from MongoDB in an undefined order
var resultsFromMongoDB = [
    _id: 7, data: "d",
    _id: 8, data: "a",
    _id: 5, data: "b",
    _id: 3, data: "c"
];

var reorderedResults = naturalOrderResults(resultsFromMongoDB, queryIds);


function naturalOrderResults(resultsFromMongoDB, queryIds) 
    //Let's build the hashmap
    var hashOfResults = resultsFromMongoDB.reduce(function (prev, curr) 
        prev[curr._id] = curr;
        return prev;
    , );

    return queryIds.map( function(id)  return hashOfResults[id]  );

【讨论】:

不错的改进!谢谢。【参考方案4】:

我遇到了同样的问题,我的解决方案是创建一个哈希映射来在我的 id 数组(我的查询)和我的 MongoDB 结果数组之间进行映射。

额外的工作是浏览结果数组并为每个项目插入一个新的键值对:键是 ID,值是结果对象。

然后,当我想以与查询相同的顺序浏览结果时,我可以使用哈希图来检索正确的对象。没有排序,也没有花哨的 Mongo DB 选项。

javascript 中是这样的:

//The order you want
var queryIds = [ 8, 5, 3, 7 ];

//The results from MongoDB in an undefined order
var resultsFromMongoDB = [
    _id: 7, data: "d" ,
    _id: 8, data: "a" ,
    _id: 5, data: "b" ,
    _id: 3, data: "c" ,
];

//The function to create a hashmap to do the mapping
function createHashOfResults( results )
    var hash = ;

    for( var i = 0 ; i < results.length ; i++ )
        var item = results[i];
        var id = item._id;
        hash[ id ] = item;
    

    return hash;


//Let's build the hashmap
var hash = createHashOfResults( resultsFromMongoDB );

//Now we can display the results in the order we want
for( var i = 0 ; i < queryIds.length ; i++ )
    var queryId = queryIds[i];
    var result = hash[queryId];
    console.log( result.data );

这将显示:

a
b
c
d

【讨论】:

我也做了同样的事情:) 如果数据很大,你不能在内存中这样做。 @JyotmanSingh - 你能理解“非常大”是什么意思吗?我需要这个功能,所以想知道它是否是一个有效的解决方案。谢谢。 @user1063287 如果您的目标是按顺序获得结果,您可以查看此解决方案:***.com/questions/22797768/…【参考方案5】:

$or 解决方法在 2.6.x 中不再有效,请参阅 https://jira.mongodb.org/browse/SERVER-14083。这是一个 Ruby 解决方法实现:https://gist.github.com/dblock/d5ed835f0147467a6a27

【讨论】:

这有点令人失望。【参考方案6】:

没有提及结果的顺序,因为它们不会以任何可靠的方式排序。让它们排序的唯一方法是在客户端对 $in 数组中的每个项目进行单独的查询

【讨论】:

好的,这就是我的预期。假设我通过 PyMongo 进行查询。然后我可以: 1. 为 id_array 中的每个 id 创建一个单独的 MongoDB 并将其附加到列表的末尾(由于查询过多而效率低下),或者 2. 进行我的问题中给出的单个 MongoDB 查询,然后使用 Python将结果从 MongoDB 复制到正确排序的列表中(效率低下,因为我在客户端复制潜在的大量数据)?没有更好的办法吗?我可以在 MongoDB 上运行某种自定义查询,在结果返回之前对其进行排序? 你可以改变你的架构。实际上,现在 mongodb-user 列表上有一个问题正在讨论该选项,正是针对这个问题。可能应该检查一下并在那里跟进。 我参加这个聚会可能有点晚了,但我刚刚遇到了这个问题。我的解决方案是构建(在我的情况下)ObjectId 的字典到位置(即,在我用于$in 查询的列表中的位置),然后使用它来重新排列输出。不过,我正在处理少量项目,所以这可能对您的情况没有帮助。 我基本上采用了与@dcrosta 相同的机制:使用原始“列表中”排序作为参考手动重新排序结果。我记得这也是 SQL 数据库的问题,所以不是 Mongo 的特性。

以上是关于对 MongoDB $in 查询的响应顺序? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB:使用 $or 运算符按条件顺序查询时如何对文档进行排序?

MongoDB地理空间查询结果未按距离顺序排列

图解MongoDB集群部署原理

使用正则表达式元素数组的 MongoDB 查询 $in

使用正则表达式元素数组的 MongoDB 查询 $in

MongoDB 中的结果顺序与 $in 类似 MySQL field('_id', ...)