如何根据第一个和最后一个嵌套数组中的值过滤包含具有 3 级嵌套数组的文档的集合中的数据 mongo
How to filter data in collection containing documents with 3 level nested arrays depending on the values in the first and last nested array mongo
在这种情况下,我很感激任何帮助。 MongoDB 中的集合(现在只有 4 个文档用于演示目的):
{
"_id" : ObjectId("62684847e9594c65cbaa5d85"),
"agentId" : NumberInt(1),
"agentName" : "Yardi Gaondi",
"policyList" : [
{
"receivedDate" : ISODate("2022-03-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-02-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-03-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(3),
"policyStatusDate" : ISODate("2022-01-16T04:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-02-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-01-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
}
]
}
{
"_id" : ObjectId("62684847e9594c65cbaa5d86"),
"agentId" : NumberInt(2),
"agentName" : "Michelle Hazandi",
"policyList" : [
{
"receivedDate" : ISODate("2022-04-10T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-04-09T05:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-03-10T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-03-09T05:46:15.000+0000")
}
]
}
]
}
]
}
{
"_id" : ObjectId("626da96932cb6043086eae42"),
"agentId" : NumberInt(3),
"agentName" : "Barbie",
"policyList" : [
{
"receivedDate" : ISODate("2022-04-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-05-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-02-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(3),
"policyStatusDate" : ISODate("2022-05-16T04:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-01-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-03-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
}
]
}
{
"_id" : ObjectId("626da96932cb6043086eae43"),
"agentId" : NumberInt(4),
"agentName" : "Mzandi",
"policyList" : [
{
"receivedDate" : ISODate("2022-05-10T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-02-09T05:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-01-10T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-02-09T05:46:15.000+0000")
}
]
}
]
}
]
}
所以集合由4个文档组成,每个文档中都有一个字段“policyList”,它是一个对象数组。在第一个文档中 policyList 包含 3 个对象,在第二个文档中只有两个,依此类推。所以我必须以这种方式过滤这个集合中的文档:1)我需要在“policyList”数组中只保留那些符合这种条件的对象:其中一个字段在某个时间间隔内,这意味着必须是至少一个字段中的匹配项(第一个字段是“receivedDate”——位于第一层嵌套的数组中——“policyList”或第二个字段“policyStatusDate”——位于第三层数组中嵌套 - “policiesArray”,如果上述字段之一匹配,我们 return 来自“policyList”完整对象,这意味着我们不能从“policiesArray”中丢弃任何对象)。一次匹配就足够了,例如,如果我想查看从 01/02/2022 到 01/03/2022 的文档,我希望在“policyList”数组的第一个文档中只看到第一个和第三个对象,因为第一个对象匹配“policyStatusDate” - 20/02/2022(匹配“policiesArray”中的一个对象就足够了)和第三个对象匹配“receivedDate” - 23/02/2022)和第一个文档中的第二个对象我不希望请参阅,因为本文档中的两个日期都不在 01/02/2022 到 01/03/2022 期间; 2)如果“policyList”中的对象之间没有任何匹配项,则意味着“policyList”在过滤后必须为空,在这种情况下我们不需要return这个文档。例如,如果我请求从 01/02/2022 到 01/03/2022 的文档,我不希望看到第二个文档,因为在请求的时间间隔内没有“policyStatusDate”和“receivedDate”。
我的聚合请求:
db.getCollection("offers2").aggregate([
{
$project: {
"agentId": "$agentId",
"agentName": "$agentName",
"policyList": {
$filter: {
input: "$policyList",
as: "item",
cond: {
"$or": [
{
"$and": [
{ "$gte": [ "$$item.receivedDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$item.receivedDate", ISODate("2022-03-01") ] }
]
},
{
$and": [
{ "$gte": [ "$$item.policyStatusDetail.policiesArray.policyStatusDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$item.policyStatusDetail.policiesArray.policyStatusDate", ISODate("2022-03-01") ] }
]
}
]
}
}
}
}
},
{
$project: {
"agentId": "$agentId",
"agentName": "$agentName",
"policyList": "$policyList",
"numPoliciesPerDate": {
$cond: {
if: {$isArray: "$policyList"}, then: {$size: "$policyList"}, else: "0"
}
}
}
},
{
$match: {
"numPoliciesPerDate": {$gte: 1}
}
}
])
在 运行 这个查询之后,我希望在“policyList”数组中收到带有第一个对象和第三个对象的第一个文档,但我只收到第三个对象(此对象中有“receivedDate”匹配)。结果:
{
"_id" : ObjectId("62684847e9594c65cbaa5d85"),
"agentId" : NumberInt(1),
"agentName" : "Yardi Gaondi",
"policyList" : [
{
"receivedDate" : ISODate("2022-02-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-01-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
}
],
"numPoliciesPerDate" : NumberInt(1)
}
...
所以看起来条件
$and": [
{ "$gte": [ "$$item.policyStatusDetail.policiesArray.policyStatusDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$item.policyStatusDetail.policiesArray.policyStatusDate", ISODate("2022-03-01") ] }
]
不正确。我认为这是因为当我们使用嵌套数组时可能无法使用点符号。所以也许有人可以帮我修复这个聚合查询,这样我在开头描述的要求就会得到满足,在我们的例子中,第一个文档中“policyList”的第一个对象也将被 returned?
我认为这个可以解决问题,只需将日期替换为您所在时区的正确格式即可:
[
{
$unwind: {
path: "$policyList"
}
},
{
$match: {
$or: [
{
"policyList.receivedDate": {
$gte: ISODate("2022-02-01T03:00:00.000Z"),
$lte: ISODate("2022-03-01T03:00:00.000Z")
}
},
{
"policyList.policyStatusDetail.policiesArray.policyStatusDate": {
$gte: ISODate("2022-02-01T03:00:00.000Z"),
$lte: ISODate("2022-03-01T03:00:00.000Z")
}
}
]
}
},
{
$group: {
_id: "$_id",
agentId: {
$first: "$agentId"
},
agentname: {
$first: "$agentName"
},
policyList: {
$push: {
receivedDate: "$policyList.receivedDate",
policyStatusDetail: "$policyList.policyStatusDetail"
}
}
}
},
{
$project: {
"agentId": "$agentId",
"agentName": "$agentName",
"policyList": "$policyList",
"numPoliciesPerDate": {
$cond: {
if: {
$isArray: "$policyList"
},
then: {
$size: "$policyList"
},
else: "0"
}
}
}
},
{
$match: {
"numPoliciesPerDate": {
$gte: 1
}
}
}
]
db.collection.aggregate(
{ "$set": {
"policyList": {
"$filter": {
"input": "$policyList",
"as": "policy",
"cond": {
"$or": [
{ "$and": [
{ "$gte": [ "$$policy.receivedDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$policy.receivedDate", ISODate("2022-03-01") ] }
]
},
{ "$reduce": {
"input": "$$policy.policyStatusDetail",
"initialValue": false,
"in": {
"$or": [
"$$value",
{ "$reduce": {
"input": "$$this.policiesArray",
"initialValue": false,
"in": {
"$or": [
"$$value",
{ "$and": [
{ "$gte": [ "$$this.policyStatusDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$this.policyStatusDate", ISODate("2022-03-01") ] }
]
}
]
}
}
}
]
}
}
}
]
}
}
}
}
},
{ "$match": { "$expr": { "$gt": [ { "$size": "$policyList" }, 0 ] } } }
)
在这种情况下,我很感激任何帮助。 MongoDB 中的集合(现在只有 4 个文档用于演示目的):
{
"_id" : ObjectId("62684847e9594c65cbaa5d85"),
"agentId" : NumberInt(1),
"agentName" : "Yardi Gaondi",
"policyList" : [
{
"receivedDate" : ISODate("2022-03-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-02-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-03-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(3),
"policyStatusDate" : ISODate("2022-01-16T04:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-02-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-01-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
}
]
}
{
"_id" : ObjectId("62684847e9594c65cbaa5d86"),
"agentId" : NumberInt(2),
"agentName" : "Michelle Hazandi",
"policyList" : [
{
"receivedDate" : ISODate("2022-04-10T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-04-09T05:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-03-10T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-03-09T05:46:15.000+0000")
}
]
}
]
}
]
}
{
"_id" : ObjectId("626da96932cb6043086eae42"),
"agentId" : NumberInt(3),
"agentName" : "Barbie",
"policyList" : [
{
"receivedDate" : ISODate("2022-04-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-05-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-02-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(3),
"policyStatusDate" : ISODate("2022-05-16T04:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-01-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-03-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
}
]
}
{
"_id" : ObjectId("626da96932cb6043086eae43"),
"agentId" : NumberInt(4),
"agentName" : "Mzandi",
"policyList" : [
{
"receivedDate" : ISODate("2022-05-10T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-02-09T05:46:15.000+0000")
}
]
}
]
},
{
"receivedDate" : ISODate("2022-01-10T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-02-09T05:46:15.000+0000")
}
]
}
]
}
]
}
所以集合由4个文档组成,每个文档中都有一个字段“policyList”,它是一个对象数组。在第一个文档中 policyList 包含 3 个对象,在第二个文档中只有两个,依此类推。所以我必须以这种方式过滤这个集合中的文档:1)我需要在“policyList”数组中只保留那些符合这种条件的对象:其中一个字段在某个时间间隔内,这意味着必须是至少一个字段中的匹配项(第一个字段是“receivedDate”——位于第一层嵌套的数组中——“policyList”或第二个字段“policyStatusDate”——位于第三层数组中嵌套 - “policiesArray”,如果上述字段之一匹配,我们 return 来自“policyList”完整对象,这意味着我们不能从“policiesArray”中丢弃任何对象)。一次匹配就足够了,例如,如果我想查看从 01/02/2022 到 01/03/2022 的文档,我希望在“policyList”数组的第一个文档中只看到第一个和第三个对象,因为第一个对象匹配“policyStatusDate” - 20/02/2022(匹配“policiesArray”中的一个对象就足够了)和第三个对象匹配“receivedDate” - 23/02/2022)和第一个文档中的第二个对象我不希望请参阅,因为本文档中的两个日期都不在 01/02/2022 到 01/03/2022 期间; 2)如果“policyList”中的对象之间没有任何匹配项,则意味着“policyList”在过滤后必须为空,在这种情况下我们不需要return这个文档。例如,如果我请求从 01/02/2022 到 01/03/2022 的文档,我不希望看到第二个文档,因为在请求的时间间隔内没有“policyStatusDate”和“receivedDate”。
我的聚合请求:
db.getCollection("offers2").aggregate([
{
$project: {
"agentId": "$agentId",
"agentName": "$agentName",
"policyList": {
$filter: {
input: "$policyList",
as: "item",
cond: {
"$or": [
{
"$and": [
{ "$gte": [ "$$item.receivedDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$item.receivedDate", ISODate("2022-03-01") ] }
]
},
{
$and": [
{ "$gte": [ "$$item.policyStatusDetail.policiesArray.policyStatusDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$item.policyStatusDetail.policiesArray.policyStatusDate", ISODate("2022-03-01") ] }
]
}
]
}
}
}
}
},
{
$project: {
"agentId": "$agentId",
"agentName": "$agentName",
"policyList": "$policyList",
"numPoliciesPerDate": {
$cond: {
if: {$isArray: "$policyList"}, then: {$size: "$policyList"}, else: "0"
}
}
}
},
{
$match: {
"numPoliciesPerDate": {$gte: 1}
}
}
])
在 运行 这个查询之后,我希望在“policyList”数组中收到带有第一个对象和第三个对象的第一个文档,但我只收到第三个对象(此对象中有“receivedDate”匹配)。结果:
{
"_id" : ObjectId("62684847e9594c65cbaa5d85"),
"agentId" : NumberInt(1),
"agentName" : "Yardi Gaondi",
"policyList" : [
{
"receivedDate" : ISODate("2022-02-23T04:46:15.000+0000"),
"policyStatusDetail" : [
{
"policyStsCode" : NumberInt(7),
"policiesArray" : [
{
"policyDetailedCode" : NumberInt(1),
"policyStatusDate" : ISODate("2022-01-20T04:46:15.000+0000")
},
{
"policyDetailedCode" : NumberInt(2),
"policyStatusDate" : ISODate("2022-01-19T05:46:15.000+0000")
}
]
}
]
}
],
"numPoliciesPerDate" : NumberInt(1)
}
... 所以看起来条件
$and": [
{ "$gte": [ "$$item.policyStatusDetail.policiesArray.policyStatusDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$item.policyStatusDetail.policiesArray.policyStatusDate", ISODate("2022-03-01") ] }
]
不正确。我认为这是因为当我们使用嵌套数组时可能无法使用点符号。所以也许有人可以帮我修复这个聚合查询,这样我在开头描述的要求就会得到满足,在我们的例子中,第一个文档中“policyList”的第一个对象也将被 returned?
我认为这个可以解决问题,只需将日期替换为您所在时区的正确格式即可:
[
{
$unwind: {
path: "$policyList"
}
},
{
$match: {
$or: [
{
"policyList.receivedDate": {
$gte: ISODate("2022-02-01T03:00:00.000Z"),
$lte: ISODate("2022-03-01T03:00:00.000Z")
}
},
{
"policyList.policyStatusDetail.policiesArray.policyStatusDate": {
$gte: ISODate("2022-02-01T03:00:00.000Z"),
$lte: ISODate("2022-03-01T03:00:00.000Z")
}
}
]
}
},
{
$group: {
_id: "$_id",
agentId: {
$first: "$agentId"
},
agentname: {
$first: "$agentName"
},
policyList: {
$push: {
receivedDate: "$policyList.receivedDate",
policyStatusDetail: "$policyList.policyStatusDetail"
}
}
}
},
{
$project: {
"agentId": "$agentId",
"agentName": "$agentName",
"policyList": "$policyList",
"numPoliciesPerDate": {
$cond: {
if: {
$isArray: "$policyList"
},
then: {
$size: "$policyList"
},
else: "0"
}
}
}
},
{
$match: {
"numPoliciesPerDate": {
$gte: 1
}
}
}
]
db.collection.aggregate(
{ "$set": {
"policyList": {
"$filter": {
"input": "$policyList",
"as": "policy",
"cond": {
"$or": [
{ "$and": [
{ "$gte": [ "$$policy.receivedDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$policy.receivedDate", ISODate("2022-03-01") ] }
]
},
{ "$reduce": {
"input": "$$policy.policyStatusDetail",
"initialValue": false,
"in": {
"$or": [
"$$value",
{ "$reduce": {
"input": "$$this.policiesArray",
"initialValue": false,
"in": {
"$or": [
"$$value",
{ "$and": [
{ "$gte": [ "$$this.policyStatusDate", ISODate("2022-02-01") ] },
{ "$lte": [ "$$this.policyStatusDate", ISODate("2022-03-01") ] }
]
}
]
}
}
}
]
}
}
}
]
}
}
}
}
},
{ "$match": { "$expr": { "$gt": [ { "$size": "$policyList" }, 0 ] } } }
)