如何使mongodb与countDocuments()和$addFields一起工作
我有一份结构如下的文件:如何使mongodb与countDocuments()和$addFields一起工作,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我有一份结构如下的文件: { '_id': '', 'a': '', 'b': '', 'c': [ { '_id': '', 'd': '', 'f': [ { 'orderDate': 12345, 'orderProfit': 12,
{
'_id': '',
'a': '',
'b': '',
'c': [
{
'_id': '',
'd': '',
'f': [
{
'orderDate': 12345,
'orderProfit': 12,
},
{
'orderDate': 67891,
'orderProfit': 12341,
},
{
'orderDate': 23456,
'orderProfit': 474,
},
],
},
{
'_id': '',
'd': '',
'f': [
{
'orderDate': 14232,
'orderProfit': 12222,
},
{
'orderDate': 643532,
'orderProfit': 4343,
},
{
'orderDate': 33423,
'orderProfit': 5555,
},
],
},
],
}
orderDate是一个int64,表示下订单的日期
orderProfit是表示订单利润的int64
我需要返回订单日期最大的文档,并检查orderProfit是否就是我要查找的。
为此,我在聚合查询中使用了如下查询:
[
{
'$addFields': {
'orders': {
'$map': {
'input': '$c',
'as': 'c',
'in': {
'profit': {
'$filter': {
'input': '$$c.f',
'cond': {
'$eq': [
{
'$max': '$$c.f.orderDate',
},
'$$this.orderDate',
],
},
},
},
},
},
},
},
},
{
'$match': {
'$or': [
{ 'orders.profit.orderProfit': 500 },
],
},
},
];
它工作正常
尝试将此查询添加到countDocuments查询以获取文档总数时会出现问题
使用这些文件是一项要求
我就是不能让它工作
$addFields作为未知的顶级运算符抛出。如果删除$addFields,则无法将查找最大日期的查询添加到countDocuments。如果我完全删除它,$match是一个未知的操作符
db.getCollection('orders').countDocuments(
{
"orders.profit.orderProfit" : {"Query that was shown previously"}
})
你不能
接收查找查询时,无法将整个管道附加到该查询
然而,countDocuments只是一个包装器
返回与集合或视图的查询匹配的文档计数。该方法使用$sum表达式包装$group聚合阶段以执行计数,并可在事务中使用
基本上,此方法只执行以下聚合:
db.collection.aggregate([
{
$match: yourQuery
},
{
$group: {
_id: null,
sum: {$sum: 1}
}
}
])
然后返回结果[0]。根据结果求和或0
因此,您可以使用自己的管道,并在最后添加此阶段,从字面上看,这将是相同的复杂性
db.collection.aggregate([
...
your entire pipeline
...
{
$group: {
_id: null,
sum: {$sum: 1}
}
}
])
如果您有任何其他特定原因不想使用聚合框架,请告诉我,也许有一个解决办法。countDocuments不允许聚合管道查询
您可以在匹配查询中使用聚合运算符,但它会导致性能问题,您可以在没有任何方法的情况下使用聚合运算符
绑定变量以在指定表达式中使用,并返回表达式的结果,
vars,为$addFields操作的订单创建变量,
在,$中,映射到$$orders.profit.orderProfit嵌套数组的迭代循环,并在条件中检查$,如果找到利润金额,则它将返回true,否则返回false
$anyElementTrue将检查返回的值是否为true,然后条件将为true,否则为false
第二种选择,用较少的操作员处理这种情况的另一种方法
$filter将您的两个条件与orderProfit匹配
$size可从以上$filter result中获取总结果
现在$map将返回过滤器返回的大小数组
$sum对返回结果编号求和,如果其大于0,则条件为真,否则为假
只需在末尾添加{$count:count}stage。不能这样做,确实需要它是一个countDocuments。因为它在另一个查询中使用。您不能在countDocuments方法中添加聚合管道。那么我如何处理它?如果您同时需要结果和计数,请使用$facet,{$facet:{result:[],count:[{$count:count}]}}}我很好奇,$count和$group by null之间有什么区别?$count也是一个包装器。它只执行以下两个阶段:db.collection.aggregate[{$group:{{u id:null,myCount:{$sum:1}}},{$project:{{u id:0}]工作正常,但实际上必须在countDocuments中使用,因为这是在golang中,并且必须转换为BSON,以便作为过滤器参数工作如何将其转换为BSON文档的任何线索?这是一个直接的查询,具有魅力,但试图将其添加到BSON文档中,以便由golang countDocuments筛选器参数进行处理是一个噩梦。对不起,我不懂go语言,请使用go、mongo go和mongo go驱动程序语言标签提出新问题。其他成员将获得确切的解决方案。
db.getCollection('orders').countDocuments({
$expr: {
$let: {
vars: {
orders: {
"$map": {
"input": "$c",
"as": "c",
"in": {
"profit": {
"$filter": {
"input": "$$c.f",
"cond": {
"$eq": [{ "$max": "$$c.f.orderDate" }, "$$this.orderDate"]
}
}
}
}
}
}
},
in: {
$anyElementTrue: {
$map: {
input: "$$orders.profit.orderProfit",
in: { $in: [500, "$$this"] }
}
}
}
}
}
})
db.getCollection('orders').countDocuments({
$expr: {
$sum: {
"$map": {
"input": "$c",
"as": "c",
"in": {
$size: {
"$filter": {
"input": "$$c.f",
"cond": {
$and: [
{ "$eq": [{ "$max": "$$c.f.orderDate" }, "$$this.orderDate"] },
{ "$eq": ["$$this.orderProfit", 500] }
]
}
}
}
}
}
}
}
})