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

时间:2019-06-29 07:50:47

标签: c# mongodb sorting indexing

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

        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();

我有一个类,其中的Metadata字段具有path和type字段,该类也具有Filename字段。我希望在元数据中具有给定路径的所有文档按类型然后按文件名排序。

示例结果将是按“名称”字段排序的文档列表,如下所示:

a, Ab, B, c, D

不幸的是,我得到了这样的东西:

Ab, B, D, a, c

那是因为MongoDB使用简单的二进制比较对数据进行排序,其中'A'<'a'是由于其ASCII码。

所以我的问题是:是否可以进行不区分大小写的排序并继续使用“ $提示”?

我传递给Find方法的选项应该告诉MongoDB使用哪个索引。我发现了这篇文章:MongoDB and C#: Case insensitive search,但是这里的方法不适用于排序,而且我无法告诉MongoDB使用哪个索引。

2 个答案:

答案 0 :(得分:2)

我认为您可以将聚合管道与$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();

答案 1 :(得分:0)

您尝试设置Collat​​ionStrenght = 2吗?

您的代码将与您需要的相似,只是在FindObject中设置排序规则:

from django.shortcuts import render, get_object_or_404, redirect
from .models import Category, Product
from django.db.models import Count
from django.contrib.auth.models import Group, User
from .forms import SignUpForm
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login, authenticate, logout
from django.core.paginator import Paginator, EmptyPage, InvalidPage

def product_list(request, category_id=None):
    category = None
    products = Product.objects.all()
    ccat = Category.objects.annotate(num_products=Count('products'))
    if category_id :
        category = get_object_or_404(Category, id=category_id)
        products = products.filter(category=category)
    paginator = Paginator('products', 3)
    try:
        page = int(request.GET.get('page', 1))
    except:
        page = 1
    try:
        products = paginator.page(page)
    except(EmptyPage, InvalidPage):
        products = paginator.page(paginator.num_pages)

    return render(request, 'products.html',
                    {'products': products,
                    'countcat':ccat})

def signupView(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get("username")
            signup_user = User.objects.get(username=username)
            customer_group = Group.objects.get(name= 'Customer')
            customer_group.user_set.add(signup_user)
    else:
        form = SignUpForm()
    return render(request, 'accounts/signup.html', {'form':form})

def signinView(request):
    if request.method == 'POST':
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            username = request.POST['username']
            password = request.POST['password']
            user = authenticate(username=username, password=password)
            if user is not None:
                login(request, user)
                return redirect('products')
            else:
                return redirect('signup')
    else:
        form = AuthenticationForm()
    return render(request, 'accounts/signin.html', {'form':form})

def signoutView(request):
    logout(request)
    return redirect('signin')