在没有阴影列的MongoDB中,有没有更好的方法进行不区分大小写的排序?

在没有阴影列的MongoDB中,有没有更好的方法进行不区分大小写的排序?,mongodb,Mongodb,我需要对几个对象执行不区分大小写的排序。我被告知不能向数据库中添加阴影列来规范化值。因此,我使用聚合对输出进行排序 我有一个简单的对象表示为: _id:ObjectID createdOn:创建对象的时间 LastUpdateOn:上次更新对象的时间 名称:对象的名称 isActive:表示对象当前是否处于活动状态的布尔值 这是我的聚合函数: db.organization.aggregate( [ { $match: { isActive: tr

我需要对几个对象执行不区分大小写的排序。我被告知不能向数据库中添加阴影列来规范化值。因此,我使用聚合对输出进行排序

我有一个简单的对象表示为:

_id:ObjectID

createdOn:创建对象的时间

LastUpdateOn:上次更新对象的时间

名称:对象的名称

isActive:表示对象当前是否处于活动状态的布尔值

这是我的聚合函数:

db.organization.aggregate(
    [
        {
            $match: { isActive: true }
        },
        {
            $project: {
                      lastUpdatedOn: 1,
                      createdOn: 1,
                      name: 1,
                      normalizedName: {$toLower: "$name"}
                      }
        },
        {
            $sort: { normalizedName: 1 }
        },
        {
            $project: {
                      lastUpdatedOn: 1,
                      createdOn: 1,
                      name: 1
                      }
        }
    ]
)

它首先确保我们只处理活动对象,为我们的排序创建规范化字段,执行排序,然后删除规范化字段,这样它就不会暴露给用户。它可以工作,并根据名称字段按字母顺序排列所有对象,但我不知道是否有更好的方法。

这不一定是一个显著的改进,但取决于您的特定用例,将原始文档从临时排序列中分离出来进行投影以捕获可能更干净:

db.organization.aggregate(
[
{
$match:{isActive:true}
},
{
$项目:{
文档:“$$ROOT”
normalizedName:{$toLower:$name}
}
},
{
$sort:{normalizedName:1}
},
{
$project:{doc:1}
}
]
)

缺点是您最终会在
doc
属性中关闭原始文档,但这很容易通过类似的方式在客户端进行清理。或者,您可以修改最终的
$project
,将每个字段提升到顶级,但这可能会很乏味。

虽然MondoDB不提供,但您可以很容易地用PHP或任何其他语言来完成。下面是如何在PHP中实现这一点

$cn = new MongoClient($dbHost);
$db = $cn->selectDB($dbName);
$col = new MongoCollection($db, $collectionName);

$cursor = $col->find();
$cursor = iterator_to_array($cursor);

foreach ($cursor as $key => $row) {
    $name[$key] = $row['name'];
    $email[$key] = $row['email'];
}
//$name is the field to sort on, taken from the above loop
//You can use SORT_ASC or SORT_DESC

array_multisort($name, SORT_ASC, $cursor);

foreach ($cursor as $doc) {
    echo $doc['name'].'-'.$doc['email'].'<br/>';
}
$cn=newmongoclient($dbHost);
$db=$cn->selectDB($dbName);
$col=新MongoCollection($db$collectionName);
$cursor=$col->find();
$cursor=迭代器到数组($cursor);
foreach($光标为$键=>$行){
$name[$key]=$row['name'];
$email[$key]=$row['email'];
}
//$name是要排序的字段,取自上面的循环
//您可以使用SORT\u ASC或SORT\u DESC
数组\u multisort($name,SORT\u ASC,$cursor);
foreach($游标为$doc){
echo$doc['name'].-.$doc['email'..
; }
我意识到这是一个老问题,但由于支持Mongo 3.4,这使得这更容易。对于具有排序规则的聚合,只需附加一个排序规则对象,如下所示:
db.organization.aggregate([pipelineobjs],{collation:{locale:'en_US'}})

我相信您的具体汇总如下所示:

db.organization.aggregate(
    [
        {
            $match: { isActive: true }
        },
        {
            $project: {
                      lastUpdatedOn: 1,
                      createdOn: 1,
                      name: 1
                      }
        },
        {
            $sort: { name: 1 }
        },
        {
            $project: {
                      lastUpdatedOn: 1,
                      createdOn: 1,
                      name: 1
                      }
        }
    ],
    {collation: {locale:'en_US'}}
)

不要这样做。您正在将整个集合加载到内存中。如果r集合大于php内存限制,则会出现内存不足错误。顺便说一句:不管怎样,在循环遍历迭代器数组时使用迭代器数组都是浪费。同意,这不是方法,只是一种解决方法。