MongoDB C# 不区分大小写的排序和索引

7

到目前为止,我一直在使用以下代码来查找我的文档并对它们进行排序:

        var options = new FindOptions
        {
            Modifiers = new BsonDocument("$hint", "PathTypeFilenameIndex")
        };

        return await Collection
            .Find(f => f.Metadata["path"] == path, options)
            .SortBy(f => f.Metadata["type"])
            .ThenBy(f => f.Filename)
            .ToListAsync();

我有一个类,其中包含路径和类型字段的元数据字段,也有一个文件名字段。我想要将所有具有给定路径的元数据内文档按类型和文件名排序。
例如,按Name字段排列的文档列表如下:
a, Ab, B, c, D

不幸的是,我得到了类似这样的结果:
Ab, B, D, a, c

这是因为 MongoDB 使用简单的二进制比较对数据进行排序,其中由于它们的 ASCII 码,“A”小于“a”。

那么我的问题是:是否有一种方法可以进行不区分大小写的排序并继续使用“$ hint”?

我通过Find方法传递的选项应告诉 MongoDB 使用哪个索引。我在这篇文章中找到了一个解决方案:MongoDB和C#:不区分大小写搜索,但这种方法不能用于排序,我无法告诉 MongoDB 使用哪个索引。

2个回答

2
我认为您可以使用聚合管道(aggregation pipeline)和$addFields$toLower(将文件名转换为小写字母),以及$sort对它们进行排序,而不考虑大小写。
在MongoDB shell中,您可以编写如下代码:
db.collection.aggregate([{
    $addFields : {
        "lowercaseFileName" : {
            $loLower : "$fileName"
        }
    },{
        $sort : {
            "metadata.type" : 1,
            lowercaseFileName : 1
        }
    }
}])

请用C#编写类似的代码,并查看它是否有效。我不懂C#,否则我会给你精确的查询,但我不能。
思路是将文件名转换为小写,将其保存在临时字段中,使用addFields进行排序。
希望这可以帮助您。
在此处阅读有关$addFields$toLower的更多信息。
更新
对于想要在C#中使用运行代码的人,感谢@kaloyan-manev 你可以使用这个:
return await Collection.Aggregate()
    .Match(f => f.Metadata["path"] == path) 
    .AppendStage<BsonDocument>(new BsonDocument("$addFields", new BsonDocument("lowercaseFileName", new BsonDocument("$toLower", "$filename")))) 
    .AppendStage<GridFSFileInfo>(new BsonDocument("$sort", new BsonDocument { {"metadata.type", 1}, {"lowercaseFileName", 1} }))
    .ToListAsync();

谢谢,我会尝试并回复您。 - Kaloyan Manev
1
如果您想添加此代码到您的答案中,请返回:return await Collection.Aggregate() .Match(f => f.Metadata["path"] == path) .AppendStage(new BsonDocument("$addFields", new BsonDocument("lowercaseFileName", new BsonDocument("$toLower", "$filename")))) .AppendStage(new BsonDocument("$sort", new BsonDocument { {"metadata.type", 1}, {"lowercaseFileName", 1} })).ToListAsync(); - Kaloyan Manev
1
此外,无需添加$hint,MongoDB足够智能,可以使用正确的索引。 - Kaloyan Manev
1
是的,我同意这一点,MongoDB足够聪明,可以使用正确的索引。 - Ravi Shankar Bharti

2

你尝试过设置CollationStrenght = 2吗?

你的代码应该类似,只需要在FindObject中设置Collation即可:

 var options = new FindOptions
    {
        Modifiers = new BsonDocument("$hint", "PathTypeFilenameIndex"),
        Collation = new Collation("en", strength: CollationStrength.Secondary)
    };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接