如何从 mongodb 中的数组中排除特定对象?
How do I exclude a sepcific object from an array in mongodb?
我有一个具有以下结构的集合:
{
"_id" : ObjectId("59ef54445134d7d70e1cf531"),
"CustomerId" : "Gym_2",
"History" : [
{
"Created_At" : ISODate("2017-10-24T14:54:59Z"),
"Unit" : 600,
"ReferenceCode" : "1cd15b4d-bc42-4a51-a8b3-307db6dc3dee",
},
{
"Created_At" : ISODate("2017-10-28T00:22:19Z"),
"Sent" : true
},
{
"Created_At" : ISODate("2017-10-29T10:22:23Z"),
"Unit" : 600,
"ReferenceCode" : "998e7fce-8a1c-4f7c-b48c-c02cb5c5ad5c",
}
]
}
{
"_id" : ObjectId("59ef54465134d7d70e1cf534"),
"CustomerId" : "Gym_1",
"History" : [
{
"Created_At" : ISODate("2017-10-24T14:55:02Z"),
"Unit" : 600,
"ReferenceCode" : "d19ebeec-bd81-4a0a-aed5-006f746b50ff",
},
{
"Unit" : 600,
"ReferenceCode" : "a991504f-be1f-4e77-b59f-fba73c59e6f1",
"Created_At" : ISODate("2017-10-26T13:51:14Z")
}
]
}
我正在尝试构建一个 returns 仅 CustomerId
的查询以及未设置 "Sent"
字段的历史对象。
结果应如下所示:
{
"_id" : ObjectId("59ef54445134d7d70e1cf531"),
"CustomerId" : "Gym_2",
"History" : [
{
"Created_At" : ISODate("2017-10-24T14:54:59Z"),
"Unit" : 600,
"ReferenceCode" : "1cd15b4d-bc42-4a51-a8b3-307db6dc3dee",
},
{
"Created_At" : ISODate("2017-10-29T10:22:23Z"),
"Unit" : 600,
"ReferenceCode" : "998e7fce-8a1c-4f7c-b48c-c02cb5c5ad5c",
}
]
}
{
"_id" : ObjectId("59ef54465134d7d70e1cf534"),
"CustomerId" : "Gym_1",
"History" : [
{
"Created_At" : ISODate("2017-10-24T14:55:02Z"),
"Unit" : 600,
"ReferenceCode" : "d19ebeec-bd81-4a0a-aed5-006f746b50ff",
},
{
"Unit" : 600,
"ReferenceCode" : "a991504f-be1f-4e77-b59f-fba73c59e6f1",
"Created_At" : ISODate("2017-10-26T13:51:14Z")
}
]
}
我能达到的最接近的是以下查询:
db.Customers.aggregate([
{$project:{"Sent":{$exists:false},count:{$size:"$History" }}}
]);
但我得到 "errmsg" : "Unrecognized expression '$exists'"
。
我怎样才能达到这个结果?
你的问题有解决方案,聚合框架绝对是实现你想要的东西的正确方法。要修改嵌套 collection,您必须:
- 放松这个 collection ($unwind)
- 过滤掉已发送的文件
- 按共同属性分组
投影您的数据以接收其原始形式
db.customers.aggregate([
{$unwind: "$History"},
{$match: {"History.Sent": {$exists: false}}},
{$group: {"_id": { "_id": "$_id", "CustomerId": "$CustomerId" }, History: { $push: "$History"} }},
{$project: { "_id": "$_id._id", "CustomerId": "$_id.CustomerId", History: 1}}
]);
如您所见,此查询相当复杂,对于较大的 collection,您可能会遇到性能问题,因为我们所做的不仅仅是简单的 collection 过滤。因此,尽管它有效,但我建议您应该考虑更改数据模型,例如将每个历史记录项作为一个单独的文档,如下所示:
{
_id: "some_id"
"Created_At" : ISODate("2017-10-24T14:54:59Z"),
"CustomerId" : "Gym_2",
"Unit" : 600,
"Sent" : true //can be set or not
"ReferenceCode" : "1cd15b4d-bc42-4a51-a8b3-307db6dc3dee"
}
那么您的查询将只是使用 $exists 的简单查找。
我有一个具有以下结构的集合:
{
"_id" : ObjectId("59ef54445134d7d70e1cf531"),
"CustomerId" : "Gym_2",
"History" : [
{
"Created_At" : ISODate("2017-10-24T14:54:59Z"),
"Unit" : 600,
"ReferenceCode" : "1cd15b4d-bc42-4a51-a8b3-307db6dc3dee",
},
{
"Created_At" : ISODate("2017-10-28T00:22:19Z"),
"Sent" : true
},
{
"Created_At" : ISODate("2017-10-29T10:22:23Z"),
"Unit" : 600,
"ReferenceCode" : "998e7fce-8a1c-4f7c-b48c-c02cb5c5ad5c",
}
]
}
{
"_id" : ObjectId("59ef54465134d7d70e1cf534"),
"CustomerId" : "Gym_1",
"History" : [
{
"Created_At" : ISODate("2017-10-24T14:55:02Z"),
"Unit" : 600,
"ReferenceCode" : "d19ebeec-bd81-4a0a-aed5-006f746b50ff",
},
{
"Unit" : 600,
"ReferenceCode" : "a991504f-be1f-4e77-b59f-fba73c59e6f1",
"Created_At" : ISODate("2017-10-26T13:51:14Z")
}
]
}
我正在尝试构建一个 returns 仅 CustomerId
的查询以及未设置 "Sent"
字段的历史对象。
结果应如下所示:
{
"_id" : ObjectId("59ef54445134d7d70e1cf531"),
"CustomerId" : "Gym_2",
"History" : [
{
"Created_At" : ISODate("2017-10-24T14:54:59Z"),
"Unit" : 600,
"ReferenceCode" : "1cd15b4d-bc42-4a51-a8b3-307db6dc3dee",
},
{
"Created_At" : ISODate("2017-10-29T10:22:23Z"),
"Unit" : 600,
"ReferenceCode" : "998e7fce-8a1c-4f7c-b48c-c02cb5c5ad5c",
}
]
}
{
"_id" : ObjectId("59ef54465134d7d70e1cf534"),
"CustomerId" : "Gym_1",
"History" : [
{
"Created_At" : ISODate("2017-10-24T14:55:02Z"),
"Unit" : 600,
"ReferenceCode" : "d19ebeec-bd81-4a0a-aed5-006f746b50ff",
},
{
"Unit" : 600,
"ReferenceCode" : "a991504f-be1f-4e77-b59f-fba73c59e6f1",
"Created_At" : ISODate("2017-10-26T13:51:14Z")
}
]
}
我能达到的最接近的是以下查询:
db.Customers.aggregate([
{$project:{"Sent":{$exists:false},count:{$size:"$History" }}}
]);
但我得到 "errmsg" : "Unrecognized expression '$exists'"
。
我怎样才能达到这个结果?
你的问题有解决方案,聚合框架绝对是实现你想要的东西的正确方法。要修改嵌套 collection,您必须:
- 放松这个 collection ($unwind)
- 过滤掉已发送的文件
- 按共同属性分组
投影您的数据以接收其原始形式
db.customers.aggregate([ {$unwind: "$History"}, {$match: {"History.Sent": {$exists: false}}}, {$group: {"_id": { "_id": "$_id", "CustomerId": "$CustomerId" }, History: { $push: "$History"} }}, {$project: { "_id": "$_id._id", "CustomerId": "$_id.CustomerId", History: 1}} ]);
如您所见,此查询相当复杂,对于较大的 collection,您可能会遇到性能问题,因为我们所做的不仅仅是简单的 collection 过滤。因此,尽管它有效,但我建议您应该考虑更改数据模型,例如将每个历史记录项作为一个单独的文档,如下所示:
{
_id: "some_id"
"Created_At" : ISODate("2017-10-24T14:54:59Z"),
"CustomerId" : "Gym_2",
"Unit" : 600,
"Sent" : true //can be set or not
"ReferenceCode" : "1cd15b4d-bc42-4a51-a8b3-307db6dc3dee"
}
那么您的查询将只是使用 $exists 的简单查找。