我正在尝试执行Mongodb聚合,这将允许我对位于查找对象中的项进行分组,并根据位于子文档中的项进行计数,例如:
客户:
- customer: {type: Schema.Types.ObjectId, ref: 'Customer'},
- [OrderLineItem]
订单:
- name: {type: Schema.Types.String, minlength: 1, maxlength: 35, required: true},
- manufacturer: {type: Schema.Types.String, minlength: 5, maxlength: 35, required: true},
- cost: {type: Schema.Types.Number, required: true},
- current_inventory: {type: Schema.Types.Number, required: true}
产品:
- product: {type: Schema.Types.ObjectId, ref: 'Product'},
- quantity: {type: Schema.Types.Number, required: true},
- total_cost: {type: Schema.Types.Number, required: true}
的OrderLineItem:
this.order.aggregate([
{$lookup: {from: "Customer", localField: "customer", foreignField: "_id", as: "customerObj"}},
{$group : {_id : {zipCode: "$customerObj.zipcode", products: "not sure what goes here...."}, total: { $count: "not sure what goes here..." }}}
])
获取通过邮政编码购买的产品总数:
@using (Html.BeginForm("CallAllocationSubmit", "Home", FormMethod.Post, new { id = "FrmCallAllocationSubmit", ReturnUrl = ViewBag.ReturnUrl }))
{
<table>
<tr>
<td>
<button class="btn btn-success btn-icon " type="submit" style="width:100px;" name="Allocate" >Allocate</button>
</td>
<td>
<button class="btn btn-primary btn-icon " type="submit" style="width:100px;" name="Defer" >Defer </button>
</td>
</tr>
</table>
}
对于上面的示例,我想获得一份按邮政编码购买的产品总数的报告。当我试图构建我的聚合时,我错过了它应该如何为这个场景编码。
答案 0 :(得分:1)
$lookup
运算符将返回&#34;数组&#34;在所有情况下匹配项目。由于客户的关系为1:1
,因此您可以通过$arrayElemAt
轻松解决该元素。
您的问题没有为包含OrderLineItem
数组的架构属性命名,因此我假设"order_lines"
位于下方,更改为您实际使用的内容。
Order.aggregate([
// lookup the customer detail
{ "$lookup": {
"from": "customers",
"localField": "customer",
"foreignField": "_id",
"as": "customer"
}},
// Group by zip
{ "$group": {
"_id": { "$arrayElemAt": [ "$customer.zipcode", 0 ] },
"total_qty": { "$sum": "$order_lines.quantity" }
}}
])
如果您需要"Product"
详细信息本身的内容,例如"manufacturer"
,并且需要将其用作$group
的一部分,那么就有必要再做$lookup
$unwind
再次,细节位于具有相同1:1
关系的数组中。但您首先需要$sum
"order_lines"
:
Order.aggregate([
// lookup the customer detail
{ "$lookup": {
"from": "customers",
"localField": "customer",
"foreignField": "_id",
"as": "customer"
}},
// $unwind the order lines
{ "$unwind": "$order_lines" },
// lookup the product detail
{ "$lookup": {
"from": "products",
"localField": "order_lines.product",
"foreignField": "_id",
"as": "order_lines.product"
}},
// Group by zip by manufacturer
{ "$group": {
"_id": {
"zip": { "$arrayElemAt": [ "$customer.zipcode", 0 ] },
"manufacturer": { "$arrayElemAt": [ "$order_lines.product.manufactuer", 0 ] }
},
"total_qty": { "$sum": "$order_lines.quantity" }
}}
])
您可能会注意到$unwind
的使用情况不会发生变化,尽管仅在一种情况下"order_lines"
数组上使用了$sum
操作。这是因为从MongoDB 3.2开始,您可以直接表示包含内部属性值的数组,因此:
"items": [{ "a": 1, "b": 2 }, { "a": 2, "b": 3 }]
当引用为"$items.a"
时:
[1,2]
此外,$group
运算符已更改,因此它也会接受&#34;数组&#34;项目以及在Setting replyTo field in email
注意集合上使用的命名约定。默认情况下,Mongoose使用给定单一模型名称的约定,即"Customer"
将是&#34;复数&#34;降为"products"
作为实际的集合名称。 $lookup
运算符在服务器上运行,而不是在了解模型的客户端代码中运行,因此服务器唯一知道的是集合。
您可能故意将您的集合命名为在猫鼬模型的声明中使用,如:
mongoose.model("Customer", customerSchema, "customer")
这意味着该集合由其正确的名称引用。但通常大多数人都不这样做,因此区分这一点非常重要。