Mongo 文档数组的项目 _id
Mongo Project _id of Array of Documents
我很难写 Mongo 查询。我永远无法理解为什么它没有 return 我所期望的,是的,我正在阅读文档,但显然很难理解。
在 Compass 中,我为带有城市文档数组的 State 集合编写了这个查询。
{"Cities.CityName":"丹佛"}
这 return 对我来说是科罗拉多州文档,其中包含文档数组中的所有城市。我下面的示例只显示了一份城市文件,但它们都在那里。
{
"_id": {"$oid":"6146ada531696ee91a3f9fa4"},
"StateName": "Colorado",
"StateCode": "CO",
"Cities": [{
"_id": {"$oid":"6146ada531696ee91a3f5a50"},
"CityName": "Denver",
"Latitude": "39.55666000",
"Longitude": "-104.89609000"
}...]
}
好的,我想清楚了,我们在 CityName 上进行了匹配,现在只需投影 City 文档的 _id。
{"Cities._id":1}
但这对我来说总是 return 州文档 id 而不是匹配的城市文档 _id。
我做错了什么?
1) 您可以使用 $ (projection) or $elemMatch (projection):
用例: 位置 $ 运算符将 <array>
的内容限制为 return 与查询匹配的第一个元素数组条件。
例如:
{ "Cities.$": 1 }
或 {"Cities": { "$elemMatch": { "CityName": "Denver" } } }
结果:
{
"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
"Cities":[{
"_id":{"$oid":"6146ada531696ee91a3f5a50"},
"CityName":"Denver",
"Latitude":"39.55666000",
"Longitude":"-104.89609000"
}]
}
Note: You have to specify the required result fields in the projection!
2) 您可以使用 $filter 聚合运算符,从 MongoDB 4.4 开始支持 find()
方法:
use case: 根据指定条件选择数组的子集到return。 Returns 仅包含符合条件的元素的数组。 returned 元素按原始顺序排列。
例如:
{
"Cities": {
"$filter": {
"input": "$Cities",
"cond": { "$eq": ["$$this.CityName", "Denver"] }
}
}
}
- 结果:
{
"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
"Cities":[{
"_id":{"$oid":"6146ada531696ee91a3f5a50"},
"CityName":"Denver",
"Latitude":"39.55666000",
"Longitude":"-104.89609000"
}...{}]
}
Note: You have to specify the required result fields in the projection!
2.1) 您可以使用 $map
聚合运算符来 select 来自 Cities
数组的 _id
:
用例: 将表达式应用于数组中的每个项目,并 return 是一个包含应用结果的数组。
例如:
{
"Cities": {
"$map": {
"input": {
"$filter": {
"input": "$Cities",
"cond": { "$eq": ["$$this.CityName", "Denver"] }
}
},
"in": "$$this._id"
}
}
}
- 结果:
{
"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
"Cities":[
{"$oid":"6146ada531696ee91a3f5a50"},
{"$oid":"6146ada531696ee91a3f5a51"},
....
]
}
Note: You have to specify the required result fields in the projection!
3) 您可以使用聚合方法 aggregate() 进行更多自定义:
- 例如:
$match
检查查询条件
$addFields
添加或格式化现有属性
$filter
和 $map 我已经在 2) point 中解释过了
db.collection.aggregate([
{ "$match": { "Cities.CityName": "Denver" } },
{
"$addFields": {
"Cities": {
"$map": {
"input": {
"$filter": {
"input": "$Cities",
"cond": { "$eq": ["$$this.CityName", "Denver"] }
}
},
"in": "$$this._id"
}
}
}
}
])
- 结果:
[
{
"Cities": [
ObjectId("6146ada531696ee91a3f5a50")
],
"StateCode": "CO",
"StateName": "Colorado",
"_id": ObjectId("6146ada531696ee91a3f9fa4")
}
]
我很难写 Mongo 查询。我永远无法理解为什么它没有 return 我所期望的,是的,我正在阅读文档,但显然很难理解。
在 Compass 中,我为带有城市文档数组的 State 集合编写了这个查询。
{"Cities.CityName":"丹佛"}
这 return 对我来说是科罗拉多州文档,其中包含文档数组中的所有城市。我下面的示例只显示了一份城市文件,但它们都在那里。
{
"_id": {"$oid":"6146ada531696ee91a3f9fa4"},
"StateName": "Colorado",
"StateCode": "CO",
"Cities": [{
"_id": {"$oid":"6146ada531696ee91a3f5a50"},
"CityName": "Denver",
"Latitude": "39.55666000",
"Longitude": "-104.89609000"
}...]
}
好的,我想清楚了,我们在 CityName 上进行了匹配,现在只需投影 City 文档的 _id。
{"Cities._id":1}
但这对我来说总是 return 州文档 id 而不是匹配的城市文档 _id。
我做错了什么?
1) 您可以使用 $ (projection) or $elemMatch (projection):
用例: 位置 $ 运算符将
<array>
的内容限制为 return 与查询匹配的第一个元素数组条件。例如:
{ "Cities.$": 1 }
或{"Cities": { "$elemMatch": { "CityName": "Denver" } } }
结果:
{
"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
"Cities":[{
"_id":{"$oid":"6146ada531696ee91a3f5a50"},
"CityName":"Denver",
"Latitude":"39.55666000",
"Longitude":"-104.89609000"
}]
}
Note: You have to specify the required result fields in the projection!
2) 您可以使用 $filter 聚合运算符,从 MongoDB 4.4 开始支持 find()
方法:
use case: 根据指定条件选择数组的子集到return。 Returns 仅包含符合条件的元素的数组。 returned 元素按原始顺序排列。
例如:
{
"Cities": {
"$filter": {
"input": "$Cities",
"cond": { "$eq": ["$$this.CityName", "Denver"] }
}
}
}
- 结果:
{
"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
"Cities":[{
"_id":{"$oid":"6146ada531696ee91a3f5a50"},
"CityName":"Denver",
"Latitude":"39.55666000",
"Longitude":"-104.89609000"
}...{}]
}
Note: You have to specify the required result fields in the projection!
2.1) 您可以使用 $map
聚合运算符来 select 来自 Cities
数组的 _id
:
用例: 将表达式应用于数组中的每个项目,并 return 是一个包含应用结果的数组。
例如:
{
"Cities": {
"$map": {
"input": {
"$filter": {
"input": "$Cities",
"cond": { "$eq": ["$$this.CityName", "Denver"] }
}
},
"in": "$$this._id"
}
}
}
- 结果:
{
"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
"Cities":[
{"$oid":"6146ada531696ee91a3f5a50"},
{"$oid":"6146ada531696ee91a3f5a51"},
....
]
}
Note: You have to specify the required result fields in the projection!
3) 您可以使用聚合方法 aggregate() 进行更多自定义:
- 例如:
$match
检查查询条件$addFields
添加或格式化现有属性$filter
和 $map 我已经在 2) point 中解释过了
db.collection.aggregate([
{ "$match": { "Cities.CityName": "Denver" } },
{
"$addFields": {
"Cities": {
"$map": {
"input": {
"$filter": {
"input": "$Cities",
"cond": { "$eq": ["$$this.CityName", "Denver"] }
}
},
"in": "$$this._id"
}
}
}
}
])
- 结果:
[
{
"Cities": [
ObjectId("6146ada531696ee91a3f5a50")
],
"StateCode": "CO",
"StateName": "Colorado",
"_id": ObjectId("6146ada531696ee91a3f9fa4")
}
]