如何从数组内的文档中投影特定字段?
Posted
技术标签:
【中文标题】如何从数组内的文档中投影特定字段?【英文标题】:How to project specific fields from a document inside an array? 【发布时间】:2016-02-23 05:38:19 【问题描述】:这是一个典型的文档
title : 'someTitle',
places : [name : 'someName', location : 'someLocation', name ...]
我有以下查询
var qs = title : 'someTitle', places : $elemMatch : name : 'someName' ;
我选择了一个与标题匹配的文档,并且该文档在其“places”数组中包含一个名称等于“someName”的文档条目。但是问题是places 数组中的条目是大型文档,我只需要该文档中的几个字段。我尝试像这样投影字段,但它不起作用。
var projection = 'places.$.name': 1, 'places.$.location' : 1;
它应该返回一个数组,其中的文档仅包含 'name'
和 'location'
属性。
我收到以下错误
Can't canonicalize query: BadValue Cannot specify more than one positional proj. per query.
说清楚,我想在没有聚合框架的情况下完成这个
【问题讨论】:
这是预期的行为。您应该考虑编辑您的问题以显示具有预期结果的示例文档。 根据docs,如果没有聚合框架,您将无法做到这一点。 我将切换到 agg 框架,我只是弃权,因为它的计算量更大,这是我应用程序的核心部分。谢谢 在我的示例中我没有使用$elemMatch
- 也许这就是我可以在数组上使用投影的原因。但我不得不省略$
。我的投影看起来像这样var projection = 'places.name': 1, 'places.location' : 1;
。在 MongoDB 3.4 中测试
【参考方案1】:
你做错了。根据documentation
投影文档中只能出现一个位置
$
运算符。
但是你仍然需要使用$
操作符才能得到预期的结果:
var qs = title : 'someTitle', 'places.name' : 'someName' ;
var projection = 'places.$': 1 ;
db.collection.find(qs, projection);
返回:
"_id" : ObjectId("564f52d7d9a433df958b5630"),
"places" : [
"name" : "someName",
"location" : "someLocation"
]
另外,您不需要 $elemMatch
运算符,请改用 "dot notation"。
现在,如果您想要的是数组中每个子文档的“名称”和“位置”数组,那么聚合就是要走的路。
db.collection.aggregate([
'$match':
'title' : 'someTitle',
'places.name' : 'someName'
,
'$project':
'places':
'$map':
'input': '$places',
'as': 'place',
'in':
'name': '$$place.name',
'location': '$$place.location'
])
产量:
"_id" : ObjectId("564f52d7d9a433df958b5630"),
"places" : [
"name" : "someName",
"location" : "someLocation"
,
"name" : "bar",
"location" : "foo"
]
【讨论】:
【参考方案2】:对于数组中的字段,可以像嵌入对象一样投影它们var projection = 'places.name': 1, 'places.location' : 1;
查看此指南https://docs.mongodb.com/manual/reference/operator/aggregation/project/#include-specific-fields-from-embedded-documents
【讨论】:
以上是关于如何从数组内的文档中投影特定字段?的主要内容,如果未能解决你的问题,请参考以下文章