根据对象内部数组对Mongo DB结果进行排序

问题描述

我们的集合中具有以下文档结构:

{
    Title: "Some product",Prices:[{
             Currency: "GBP",Value: 10
           },{
             Currency: "USD",Value: 15
           }
    ]
}

我们正尝试使用C#BSON驱动程序根据特定货币的价格订购这些文档:

sort = Builders<ProductSearchData>.sort.Ascending(x => x.Prices.First(x=>x.Currency == currency).Value);

然后将其传递给集合:

        var results = await Collection.FindAsync(filter,new FindOptions<ProductSearchData>
        {
            Sort =  sort,Skip = page*pageSize,Limit =  pageSize
        });

但是,这没有给出正确的排序顺序。相反,值似乎随机返回。以上语法是正确的还是我们应该以其他方式查询

如果我们进行更简单的排序,例如

sort = Builders<ProductSearchData>.sort.Descending(x => x.Title);

一切正常。

通过登录Mongo,我们似乎得到了以下两个查询

 "{ "find" : "ProductSearch","filter" : { "Prices" : { "$elemmatch" : { "Currency" : 10,"Value" : { "$gte" : 0,"$lte" : 10000 } } },"IsActive" : true },"sort" : { "Value" : 1 },"skip" : 0,"limit" : 10,"$db" : "MyForest_Data","lsid" : { "id" : CSUUID("d4caa989-9493-41a7-bcde-81f198beda7a") } }"



{ "aggregate" : "ProductSearch","pipeline" : [{ "$match" : { "Prices" : { "$elemmatch" : { "Currency" : 10,"IsActive" : true } },{ "$group" : { "_id" : 1,"n" : { "$sum" : 1 } } }],"cursor" : { },"lsid" : { "id" : CSUUID("d4caa989-9493-41a7-bcde-81f198beda7a") } }

解决方法

并不是解决问题的真正答案,而是对发生的情况的解释:

到达数据库的查询是

"find" : "ProductSearch","filter" : { 
    "Prices" : { 
        "$elemMatch" : { 
            "Currency" : 10,"Value" : { "$gte" : 0,"$lte" : 10000 } 
        } 
    },"IsActive" : true 
},"sort" : { "Value" : 1 },"skip" : 0,"limit" : 10,

它将搜索价格在0到10,000之间的特定货币的文档,然后按顶级字段Value进行排序。我的猜测不是OP想要的,根本没有这样的字段,因此文档以自然顺序返回。

快速搜索会带来MongoDB find subdocument and sort the results,这似乎是对匹配的子文档进行排序的合理方法。

,

怎么样:

collection.AsQueryable()
            .SelectMany(x => x.Prices,(x,pr) => new { T = x.Title,V = pr.Value,C = pr.Currency } )
            .Where(x => x.C == "GBP")
            .OrderBy(x => x.V)
            .Skip(0)
            .Take(100)
  • 跳过并进行分页...
,

我调查了其他两个答案的建议,但是找不到一种干净的方法来执行UnWind命令,该命令允许我们在MongoDB C#库中使用Builders。此外,在反思时,我们担心MongoDB的性能影响必须对每个查询执行内存释放。

相反,我们决定在建立索引过程中“放松”“价格”字段。当我们将产品编入搜索集合中时,我们会为产品具有的每种货币创建一个记录。我们还设置了一个组ID,该ID允许我们标识所有相关记录以进行清理:

        var results = new IndexingData();

        results.GroupId = source.Id.ToString();

        foreach (var price in source.Prices)
        {
            var searchData =  new ProductSearchRecord()
            {
                Id=  $"{source.Id}{price.Currency}",GroupId =  source.Id.ToString(),Title =  source.Title,Price= price,};

            results.Records.Add(searchData);
        }


        return results;

插入集合:

        var indexingData = GetRecords(source);

        await Collection.DeleteManyAsync(x => x.GroupId == indexingData.GroupId);

        foreach (var record in indexingData.Records)
        {
            await Collection.ReplaceOneAsync(x => x.Id == record.Id,record,new UpdateOptions() {IsUpsert = true});
        }

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...