nir*_*rji 6 java mongodb mongodb-query aggregation-framework
这是我的查询,
db.product.aggregate([
{ $match : {categoryID : 4 } },
{ "$group" : { "_id" : { "productID": "$productID",
"articleID": "$articleID", "colour":"$colour",
"set&size": { "sku" : "$skuID", "size" : "$size" },
},
}
},
{ "$group" : { "_id" : { "productID": "$_id.productID", "colour":"$_id.colour" },
"size": { "$addToSet" : { "sku" : "$_id.set&size.sku",
"size" : "$_id.set&size.size" }
},
}
},
{"$project":{
"_id":0,
"productID": "$_id.productID",
"colour":"$_id.colour",
"size":"$size",
}
},
]);
Run Code Online (Sandbox Code Playgroud)
通过在mongo shell上执行此查询,我得到了完美的输出.
产量
{
"_id": {
"productID": "PRD1523",
"colour": "GREEN"
},
"size": [
{
"sku": "ALT50095",
"size": "S"
},
{
"sku": "ALT50096",
"size": "XL"
}
]
}
{
"_id": {
"productID": "PRD1523",
"colour": "RED"
},
"size": [
{
"sku": "ALT50094",
"size": "M"
},
{
"sku": "ALT50093",
"size": "S"
}
]
}
Run Code Online (Sandbox Code Playgroud)
但是当我使用我的java代码时,它会给出异常.
这是上面查询的java代码,
DBCollection table = mongoTemplate.getCollection(collection_name);
BasicDBObject matchTopics = new BasicDBObject();
matchTopics.put("categoryID", 4);
DBObject groupSameIdEntities = new BasicDBObject("_id", new BasicDBObject("productID", "$productID")
.append("articleID", "$articleID").append("colour", "$colour")
.append("set&size", new BasicDBObject("sku", "$skuID").append("size", "$size")));
DBObject secondGroup = new BasicDBObject("_id", new BasicDBObject("colour", "$_id.colour").append("productID",
"$_id.productID").append(
"size",
new BasicDBObject("$addToSet", new BasicDBObject("sku", "$_id.set&size.sku").append("size",
"$_id.set&size.size"))));
AggregationOutput output = table.aggregate(new BasicDBObject("$match", matchTopics), new BasicDBObject(
"$group", groupSameIdEntities), new BasicDBObject("$group", secondGroup));
Run Code Online (Sandbox Code Playgroud)
例外
HTTP状态500 - 请求处理失败; 嵌套异常是com.mongodb.CommandFailureException:{"serverUsed":"127.0.0.1:27017","errmsg":"异常:无效的运算符'$ addToSet'","code":15999,"ok":0.0}
我无法弄清楚如何解决这个错误.
通常,最好的方法是独立于调用方法来定义完整的聚合管道,并遵循与您在此处找到并使用的 JSON 示例中相同的结构和缩进规则。
这样,就可以更容易地看出哪里偏离了结构:
List<DBObject> pipeline = Arrays.<DBObject>asList(
new BasicDBObject("$match",new BasicDBObject("categoryID", 4)),
new BasicDBObject("$group",
new BasicDBObject("_id",
new BasicDBObject("productID","$productID")
.append("articleID", "$articleID")
.append("colour", "$colour")
.append("size",
new BasicDBObject("sku","$skuID")
.append("size","$size")
)
)
),
new BasicDBObject("$group",
new BasicDBObject("_id",
new BasicDBObject("productID","$_id.productID")
.append("articleID", "$_id.articleID")
.append("colour", "$_id.colour")
)
.append("size",new BasicDBObject("$push","$_id.size")
),
new BasicDBObject("$project",
new BasicDBObject("_id",0)
.append("productID","$_id.productID")
.append("colour","$_id.colour")
.append("size",1)
)
);
Run Code Online (Sandbox Code Playgroud)
另请注意此处的一些简化命名并使用$push而不是$addToSet。最后一个通常是因为您已经通过将其包含在第一$group阶段中来确定唯一值,因此 an$addToSet在这里不会做任何有价值的事情,实际上会从早期阶段的结果中删除任何固有的顺序,或者如果您故意订购了。
从这个意义上讲,您当然可以缩短为单个,$group就像$addToSet执行它自己的“不同”操作一样:
List<DBObject> pipeline = Arrays.<DBObject>asList(
new BasicDBObject("$match",new BasicDBObject("categoryID", 4)),
new BasicDBObject("$group",
new BasicDBObject("_id",
new BasicDBObject("productID","$productID")
.append("articleID", "$articleID")
.append("colour", "$colour")
)
.append("size",new BasicDBObject("$addToSet",
new BasicDBObject("sku","$skuID")
.append("size","$size")
)
)
);
Run Code Online (Sandbox Code Playgroud)
我还建议删除最后一个,$project因为它本质上需要传递所有结果并更改所有存在的文档。这只是添加到通常在客户端上可以更好处理的处理。
一般来说,聚合管道阶段越少越好,除非发生重大事件,否则另一个软件层可能比数据库服务器更好地处理它。
| 归档时间: |
|
| 查看次数: |
2795 次 |
| 最近记录: |