【发布时间】:2016-02-18 01:16:32
【问题描述】:
我在 MongoDB 中的集合具有以下结构
{
'_id': 45
'tags': [ 'tag 1', 'tag 3' ]
'active': true
'fields': [
{ 'name': 'common field 1', 'type': 'text', 'value': 'some text', ... },
{ 'name': 'common field 2', ... },
{ 'name': 'multivalued field 1',
'type': 'multifield',
'valueCount': 5,
'value': [
{ 'name': 'subfield1', ..., 'value': [1, 2, 3, 4, 5]},
{ 'name': 'subfield2', ..., 'value': ["one", "two", "three", "four", "five"]},
{ 'name': 'subfield3', ..., 'value': ["here", "there", "", "", ""]}
], ... }
]
}
我正在尝试在我的 API 中实现投影:例如,如果用户请求
api/collection/?fields=id,fields{common field 2, multifield{subfield1}}
结果应该是
{
'_id': 45
'fields': [
{ 'name': 'common field 1', 'type': 'text', 'value': 'some text', ... },
{ 'name': 'multivalued field 1',
'type': 'multifield',
'valueCount': 5,
'value': [
{ 'name': 'subfield1', ..., 'value': [1, 2, 3, 4, 5]},
], ... }
]
}
由于“字段”名称不是实际的键,我不能使用 mongo 投影,比如说
db.collection.find({},{_id: 1, tags: 1, fields.'common field 1': 1})
所以我必须改为在数组中搜索“名称”属性与我的投影参数匹配的字段。正如这个答案https://stackoverflow.com/a/24032549/5418731
中所建议的,我通过聚合和 $redact 实现了第一级数组db.points.aggregate([
{ $match: {}},
{
$project: {_id :1, fields: 1}
},
{ $redact : {
$cond: {
if: { $or : [{ $not : "$name" }, { $eq: ["$name", "common field 1"] }]},
then: "$$DESCEND",
else: "$$PRUNE"
}
}}])
但是,我不能使用 $redact 从多值字段的内部数组中选择子字段。 $or 参数必须类似于
[{ $not : "$name" }, { $eq: ["$name", "common field 1"] }, { $eq: ["$name", "subfield1"] }]
这意味着与指定的子字段具有相同名称的第一级字段也将通过。
将 MongoDB 升级到 3.2 后,我尝试了这个答案 https://stackoverflow.com/a/12241930/5418731 中的 $filter 解决方案,它也适用于一级数组:
db.points.aggregate([
{$project: {
fields: {$filter: {
input: '$fields',
as: 'field',
cond: {$eq: ['$$field.name', 'multivalued field 1']}
}}
}}
])
但我找不到“嵌套”使用它并过滤二级数组项的方法。添加{$eq: ['$$field.value.name', 'subfield1']} 不起作用。
最后,我尝试了这里介绍的 $map 解决方案https://stackoverflow.com/a/24156418/5418731:
db.points.aggregate([
{ "$project": {
"_id": 1,
"fields": {
"$map": {
"input": "$fields",
"as": "f",
"in": {
"$ifNull": [
{
"name": "$multivalued field 1",
"type": "$multifield", //attempt to restrict search to fields with arrays as values
"value": {
"$map": {
"input": "$$f.value",
"as": "v",
"in": {
"$ifNull": [
{ "name": "$subfield1"},
false
]
}
}
}
},
false
]
}
}
}
}}
])
但是这个不起作用,因为每个“字段”项的“值”属性不一定是一个数组,如果不是,整个查询就会失败。
我即将放弃并掩盖 JS 中的结果。 Mongo 有什么好的解决方案吗?
【问题讨论】:
标签: arrays mongodb subdocument