我有以下文件:
{
_id : 1,
key1 : {
samekeyA : "value1",
samekeyB : "value2"
},
key2 : {
samekeyA : "value3",
samekeyB : "value4"
},
key3 : {
samekeyA : "value5",
samekeyB : "value6"
}
}
以上; key1
,key2
和key3
用来证明我不知道完整密钥,除了它的前缀之外;但我认识的内键samekeyA
和samekeyB
。我需要查询:db.coll.find({"key*.samekeyA":"value1"})
。
我认为没有mongo方式 - 正则表达式关键查询? - 要实现这一点,那么有什么想法吗?我应该改造我的文件 - 树吗?
答案 0 :(得分:2)
我建议重组模型。
{
_id : 1,
data: [ {
key : "key1",
samekeyA : "value1",
samekeyB : "value2"
},
{
key : "key2",
samekeyA : "value3",
samekeyB : "value4"
},
{
key : "key3",
samekeyA : "value5",
samekeyB : "value6"
}
]
}
查询:
db.col.find({"data.samekeyA": "value1"})
目前(也可能在未来),不可能在字段名中使用通配符查询MongoDB集合(感谢@gWiz)。
答案 1 :(得分:1)
使用MongoDB 3.4.4和更高版本:
db.coll.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": {
"$eq": [
"$$el.v.samekeyA",
"value1"
]
}
}
}
}
} }
])
上述管道将产生最终输出
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
可以分解管道以显示每个操作员的结果。
$objectToArray
使您可以使用动态键转换根文档
(由系统变量 $$ROOT
表示)放入一个数组,该数组包含原始文档中每个字段/值对的元素。返回数组中的每个元素都是一个包含两个字段k和v的文档。
在 $project
阶段仅由操作员运行管道
db.coll.aggregate([
{ "$project": {
"keys": { "$objectToArray": "$$ROOT" }
} }
])
收益
{
"_id" : 1,
"keys" : [
{
"k" : "_id",
"v" : 1
},
{
"k" : "key1",
"v" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
},
{
"k" : "key2",
"v" : {
"samekeyA" : "value3",
"samekeyB" : "value4"
}
},
{
"k" : "key3",
"v" : {
"samekeyA" : "value5",
"samekeyB" : "value6"
}
}
]
}
$filter
运算符充当 $objectToArray
运算符生成的数组的过滤机制,它通过选择数组的子集来工作根据指定条件返回
成为您的查询。
考虑以下管道,该管道返回与条件{ "samekeyA": "value1" }
相匹配的键/值对的数组
db.coll.aggregate([
{ "$project": {
"keys": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": {
"$eq": [
"$$el.v.samekeyA",
"value1"
]
}
}
}
} }
])
产生
{
"_id" : 1,
"keys" : [
{
"k" : "key1",
"v" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
]
}
这将从
转换上面的过滤数组[
{
"k" : "key1",
"v" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
]
使用动态键到原始文档
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
所以要运行管道
db.coll.aggregate([
{ "$project": {
"key": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": {
"$eq": [
"$$el.v.samekeyA",
"value1"
]
}
}
}
}
} }
])
会产生
{
"_id" : 1,
"key" : {
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
}
这会将筛选后的动态密钥文档提升到最高级别,并替换所有其他字段。该操作将替换输入文档中的所有现有字段,包括_id
字段。
从本质上讲,这可以转换上面的文档
{
"_id" : 1,
"key" : {
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
}
达到所需的最终输出
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}