我有以下数据。我想根据某些条件从 od 数组中获取对象。除此之外,我还想获得它们和名称字段。
我不太熟悉aggregate of mongodb 。所以我需要帮助来解决我的问题。
{
_id : 1,
em : '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="69080b0a29585b1a47070c1d" rel="noreferrer noopener nofollow">[email protected]</a>',
name : 'NewName',
od :
[
{
"oid" : ObjectId("1234"),
"ca" : ISODate("2016-05-05T13:20:10.718Z")
},
{
"oid" : ObjectId("2345"),
"ca" : ISODate("2016-05-11T13:20:10.718Z")
},
{
"oid" : ObjectId("57766"),
"ca" : ISODate("2016-05-13T13:20:10.718Z")
}
]
},
{
_id : 2,
em : '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a5c4c793c6e5dddcdf8bcbc0d1" rel="noreferrer noopener nofollow">[email protected]</a>',
name : 'NewName2',
od :
[
{
"oid" : ObjectId("1234"),
"ca" : ISODate("2016-05-11T13:20:10.718Z")
},
{
"oid" : ObjectId("2345"),
"ca" : ISODate("2016-05-12T13:20:10.718Z")
},
{
"oid" : ObjectId("57766"),
"ca" : ISODate("2016-05-05T13:20:10.718Z")
}
]
}
我尝试使用 $match、$project 和 $unwind 聚合来获得所需的结果。我的查询如下:-
db.collection.aggregate([
{
$match : {
"od.ca" : {
'$gte': '10/05/2016',
'$lte': '15/05/2016'
}
}
},
{
$project:{
_id: '$_id',
em: 1,
name : 1,
od : 1
}
},
{
$unwind : "$od"
},
{
$match : {
"od.ca" : {
'$gte': '10/05/2016',
'$lte': '15/05/2016'
}
}
}])
我得到的结果是 em 和 name 以及 od 数组以及来自 od 的对象之一,即同一电子邮件 ID 有多个记录。
{
_id : 1,
em : '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3b5a59587b0a094815555e4f" rel="noreferrer noopener nofollow">[email protected]</a>',
name : 'NewName',
od :
[
{
"oid" : ObjectId("57766"),
"ca" : ISODate("2016-05-13T13:20:10.718Z")
}
]
}
{
_id : 1,
em : '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="02636061423330712c6c6776" rel="noreferrer noopener nofollow">[email protected]</a>',
name : 'NewName',
od :
[
{
"oid" : ObjectId("2345"),
"ca" : ISODate("2016-05-11T13:20:10.718Z")
}
]
}
但是我想要的是每个电子邮件 ID 的返回结果,在 od 数组内所有与条件匹配的对象。我想要的一个输出示例是:-
{
_id : 1,
em : '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3b5a59587b0a094815555e4f" rel="noreferrer noopener nofollow">[email protected]</a>',
name : 'NewName',
od :
[
{
"oid" : ObjectId("2345"),
"ca" : ISODate("2016-05-11T13:20:10.718Z")
},
{
"oid" : ObjectId("57766"),
"ca" : ISODate("2016-05-13T13:20:10.718Z")
}
]
}
我在查询中做错了什么吗?如果查询应该像这样返回,我怎样才能得到我想要的结果?有人可以告诉我应该尝试什么或者查询中的哪些更改可以帮助我获得我想要的结果吗?
最佳答案
您不一定需要一组这些聚合运算符,除非您的 MongoDB 版本早于 2.6.X
版本。 $filter
运算符(operator)会很好地完成这项工作。
考虑以下示例,其中 $filter
运算符应用于 $project
时 管道阶段将过滤 od
数组,仅包含 ca
日期大于或等于 '2016-05-10'< 的文档
且小于或等于 '2016-05-15'
:
var start = new Date('2016-05-10'),
end = new Date('2016-05-15');
db.collection.aggregate([
{
"$match": {
"od.ca": { "$gte": start, "$lte": end }
}
},
{
"$project": {
"em": 1,
"name": 1,
"od": {
"$filter": {
"input": "$od",
"as": "o",
"cond": {
"$and": [
{ "$gte": [ "$$o.ca", start ] },
{ "$lte": [ "$$o.ca", end ] }
]
}
}
}
}
}
])
请记住,此运算符仅适用于 MongoDB 版本 3.2.X
及更高版本。
否则,对于 2.6.X
至 3.0.X
版本,您可以结合使用 $map
和 $setDifference
运算符来“过滤”ca 数组中的文档。
$map
运算符基本上映射由 $cond
计算的一些值。 运算符连接到一组错误值或通过给定条件的文档。 $setDifference
运算符然后返回与先前计算的集合的差值。通过前面的示例检查结果如何:
var start = new Date('2016-05-10'),
end = new Date('2016-05-15');
db.collection.aggregate([
{
"$match": {
"od.ca": { "$gte": start, "$lte": end }
}
},
{
"$project": {
"em": 1,
"name": 1,
"od": {
"$setDifference": [
{
"$map": {
"input": "$od",
"as": "o",
"in": {
"$cond": [
{
"$and": [
{ "$gte": [ "$$o.ca", start ] },
{ "$lte": [ "$$o.ca", end ] }
]
},
"$$o",
false
]
}
}
},
[false]
]
}
}
}
])
对于 2.4.X 及更早版本,您可能必须使用 $match
的组合。 , $unwind
和 $group
运算符以在上述运算符不存在的情况下实现相同的效果。
前面的示例演示了这一点,这就是您所尝试的,但缺少 $group
管道步骤,将所有扁平化文档分组到原始文档架构中,尽管减去过滤后的数组元素:
db.collection.aggregate([
{
"$match": {
"od.ca": { "$gte": start, "$lte": end }
}
},
{ "$unwind": "$od" },
{
"$match": {
"od.ca": { "$gte": start, "$lte": end }
}
},
{
"$group": {
"$_id": "$_id",
"em": { "$first": "$em" },
"name": { "$first": "$name" },
"od": { "$push": "$od" }
}
}
])
关于javascript - 根据某些条件,使用 mongodb 聚合从数组中获取对象以及同一级别的其他字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37340008/