我们的集合中具有以下文档结构:
{
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, "Value" : { "$gte" : 0, "$lte" : 10000 } } }, "IsActive" : true } }, { "$group" : { "_id" : 1, "n" : { "$sum" : 1 } } }], "cursor" : { }, "$db" : "MyForest_Data", "lsid" : { "id" : CSUUID("d4caa989-9493-41a7-bcde-81f198beda7a") } }
答案 0 :(得分:0)
并不是解决问题的真正答案,而是对发生的情况的解释:
到达数据库的查询是
"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,这似乎是对匹配的子文档进行排序的合理方法。
答案 1 :(得分:0)
怎么样:
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)
答案 2 :(得分:0)
我调查了其他两个答案的建议,但是找不到一种干净的方法来执行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});
}