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

问题描述 投票:1回答:3

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

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

_id:ObjectID

createdOn:创建了时间对象

lastUpdatedOn:上次更新时间对象

name:对象的名称

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
                      }
        }
    ]
)

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

mongodb
3个回答
2
投票

它不一定是一个显着的改进,但根据您的具体用例,投影$$ROOT以捕获与临时排序列分开的原始文档可以更清晰:

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

缺点是你最终在doc财产中关闭了原始文档,但是很容易通过像Array#map这样的东西来清理客户端。或者您可以修改最终的$project以将每个字段提升到顶级,但这可能很乏味。


0
投票

虽然MongoDB不提供它,但你可以很容易地用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/>';
}

0
投票

我意识到这是一个古老的问题,但由于支持Mongo 3.4 Collation,这使得这更容易。对于Collat​​ion with Collat​​ion,只需附加一个如下的校对对象: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'}}
)
© www.soinside.com 2019 - 2024. All rights reserved.