繁体   English   中英

没有影子列的MongoDB是否有更好的区分大小写的排序方式?

[英]Is there a better way of doing case insensitive sort in MongoDB without shadow columns?

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

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

_id:ObjectID

createdOn:创建时间对象

lastUpdatedOn:时间对象上次更新

名称:对象的名称

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

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

不一定有很大的改进,但是根据您的特定用例,将$$ROOT投影为捕获与临时排序列分开的原始文档可能会更干净:

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

不利的一面是您最终将原始文档放在doc属性中,但是可以通过Array#map类的内容轻松清除客户端。 或者,您可以修改最终的$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/>';
}

我意识到这是一个古老的问题,但是由于支持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'}}
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM