$in条件运算符上的MongoDB文档没有说明订单。如果我运行表单
的查询db.things.find({'_id': {'$in': id_array}});
返回结果的顺序是什么?我有没有办法告诉MongoDB“我希望结果排序,以便它们与id_array
中的ID的顺序相同?”
答案 0 :(得分:11)
在JIRA上询问此功能:
很快得到了很好的回复:使用$or
代替$in
c.find( { _id:{ $in:[ 1, 2, 0 ] } } ).toArray()
VS
c.find( { $or:[ { _id:1 }, { _id:2 }, { _id:0 } ] } ).toArray()
阅读错误报告以获取更多信息。
<强>更新强>:
从2.6.x开始,$或解决方法的hack不再起作用 - 这是实现的副作用changed。
答案 1 :(得分:6)
我有同样的问题,我的解决方案是创建一个哈希映射来执行我的数组(我的查询)和我的MongoDB结果数组之间的映射。
额外的工作是浏览结果数组并为每个项插入一个新的键值对:键是ID,值是结果对象。
然后,当我想以与查询相同的顺序浏览我的结果时,我可以使用hashmap来检索正确的对象。没有排序,也没有花哨的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
答案 2 :(得分:5)
关于其他答案:我不建议逐个查询,因为它会带来严重的性能问题。
除了@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] } );
}
答案 3 :(得分:4)
未提及结果的顺序,因为它们不会以任何可靠的方式排序。获取它们的唯一方法是对$ in数组中的每个项目进行单独的客户端查询
答案 4 :(得分:3)
如果你不介意使用Underscore.js并且不太担心规模(IE,你不要介意fetch
- 而不是使用光标),这是我维持秩序的方式:
var results = db.things.find({'_id': {'$in': id_array}}).fetch();
return _.sortBy(results, function(thing) {
return id_array.indexOf(thing._id);
});
答案 5 :(得分:2)
$或解决方法在2.6.x中不再有效,请参阅https://jira.mongodb.org/browse/SERVER-14083。这是一个Ruby解决方案实现:https://gist.github.com/dblock/d5ed835f0147467a6a27