我遇到mongodb查找问题。以下是如何重现我的问题的基本示例
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
public class OrderProduct
{
public string ProductId { get; set; }
public int Quantity { get; set; }
}
public class Order
{
public string Id { get; set; }
public List<OrderProduct> OrderProducts { get; set; }
public double Total { get; set; }
}
我想获得订单和所有相关产品。 所以这是我的查询
var filter = Builders<Entities.Order>.Filter.Eq(x => x.Id, id);
var result = await Collection.Aggregate()
.Match(filter)
.Lookup("Product", "OrderProducts.ProductId", "_id", "Products")
.FirstOrDefaultAsync();
所以基本上我成功地从集合中获取数据,但格式有点不同。我正在收到BsonDocument
{
{
"_id":"5ab0c1ec36e4e937302ee1df",
"Total":225,
"OrderProducts":
[
{
"ProductId":"5ab0c1dc36e4e937302ee1de",
"Quantity":2
}
],
Products:
[
{
"_id":"5ab0c1dc36e4e937302ee1de",
"Name":"Test product",
"Price":20
}
]
}
但我想得到这样的文件:
{
{
"_id":"5ab0c1ec36e4e937302ee1df",
"Total":225,
"OrderProducts":
[
{
"_id":"5ab0c1dc36e4e937302ee1de",
"Name":"Test product",
"Price":20,
"Quantity":2
}
]
}
您对如何实现这一点有什么想法吗?我找到了运算符mergeObject但我不知道如何在这里添加它。还有一个:是否有更优雅的方式来指定查找?这里没有硬编码的字符串.Lookup("Product", "OrderProducts.ProductId", "_id", "Products")
答案 0 :(得分:0)
为避免硬编码字符串,您可以使用nameof
运算符。要获得所需的形状,您需要摆脱数组(使用Unwind
),然后使用Lookup
,然后分组回单Order
尝试:
var filter = Builders<Order>.Filter.Eq(x => x.Id, id);
var result = Collection.Aggregate<Order>()
.Match(filter)
.Unwind(a => a.OrderProducts)
.Lookup(nameof(Product), $"{nameof(Order.OrderProducts)}.{nameof(OrderProduct.ProductId)}", "_id", nameof(Product))
.Unwind(nameof(Product))
.Group(new BsonDocument
{
{ "_id", "_id" },
{ nameof(Order.Total) , new BsonDocument("$first", $"${nameof(Order.Total)}")},
{ nameof(Order.OrderProducts),
new BsonDocument("$push",
new BsonDocument() {
{ "_id", $"${nameof(Product)}._id" },
{ nameof(Product.Name), $"${nameof(Product)}.{nameof(Product.Name)}" },
{ nameof(Product.Price), $"${nameof(Product)}.{nameof(Product.Price)}" },
{ nameof(OrderProduct.Quantity), $"${nameof(OrderProduct)}s.{nameof(OrderProduct.Quantity)}" }
}
)},
})
.FirstOrDefault();