我有查询
$cursor = $collection->find(array('id' =>array('$in'=>array(4,3,2,1))), array('name'));
foreach($cursor as $fild)
{
echo $fild['name'].'<br>';
}
返回
Need for speed: Most Wanted
Pro Evolution Soccer 2014
Fifa 2014
Star Craft 2
如果我改变数组中的顺序,如(3,2,4,1)。 返回
Need for speed: Most Wanted
Pro Evolution Soccer 2014
Fifa 2014
Star Craft 2
必须返回
Fifa 2014
Pro Evolution Soccer 2014
Star Craft 2
Need for speed: Most Wanted
我做错了什么?
答案 0 :(得分:0)
基本上,这不是$in
运算符的工作方式,对于MongoDB或任何数据库中的任何等效形式。因此,您放入参数的顺序不会保留在您的结果中,因为您似乎期望它们。
但是,为了实现这一目标,您可以采取几种方法。第一个是通过聚合管道的一些创造性使用:
var selections = [ 4, 2, 3, 1 ];
db.collection.aggregate([
// $match is like a standard "find" query
{ "$match": {
"id": { "$in": selections }
}},
// Project your field(s) and a sorting field
{ "$project": {
"_id": 0,
"name": 1,
"order": { "$cond": [
{ "$eq": [ "$id", 4 ] },
1,
{ "$cond": [
{ "$eq": [ "$id", 2 ] },
2,
{ "$cond": [
{ "$eq": [ "$id", 3 ] },
3,
4
]}
]}
]}
}},
// Sort on the generated field
{ "$sort": { "order": } }
])
因此,使用$cond
运算符(ternary operator),您正在评估id
的当前值,以确定要分配的排序顺序。当然,您实际上会使用类似于shown here的方法在代码中为此条件生成管道内容。
当然,如果这看起来有点过于复杂,即使您最好这样做,那么您可以使用mapReduce以类似的方式解决问题。但由于这在解释器中使用JavaScript代码并且不使用aggregate
之类的本机代码,因此运行速度会变慢:
var selections = [ 4, 2, 3, 1 ];
db.collection.mapReduce(
function() {
emit(
selections.indexOf( this.id ),
this.name
);
},
function(){},
{
"query": { "id": { "$in": selections } },
"scope": { "selections": selections },
"out": { "inline": 1 }
}
)
这种方式利用了mapReduce如何对映射器中发出的键值进行排序,因此通过按照数组中的索引值进行定位可以保持排序顺序。
因此,您可以使用几种方法来“动态”生成排序顺序,类似于数组中参数的顺序。