anv*_*rik 1 database-design mongodb aggregation-framework
我有以下文件:
{
_id : 1,
key1 : {
samekeyA : "value1",
samekeyB : "value2"
},
key2 : {
samekeyA : "value3",
samekeyB : "value4"
},
key3 : {
samekeyA : "value5",
samekeyB : "value6"
}
}
Run Code Online (Sandbox Code Playgroud)
以上; key1,key2并被key3用来证明我不知道完整的密钥,除了它的前缀;但内在的钥匙samekeyA和samekeyB我知道的那些。我需要查询,例如:db.coll.find({"key*.samekeyA":"value1"})。
我认为没有一种 mongo 方式 - 正则表达式键查询? - 来实现这一点,所以有什么想法吗?我应该改造我的文档-tree-吗?
使用 MongoDB 3.4.4 及更新版本:
db.coll.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": {
"$eq": [
"$$el.v.samekeyA",
"value1"
]
}
}
}
}
} }
])
Run Code Online (Sandbox Code Playgroud)
上述管道将产生最终输出
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
Run Code Online (Sandbox Code Playgroud)
可以分解管道以显示每个操作员的结果。
$objectToArray使您能够将具有动态键(由系统变量表示$$ROOT)的根文档转换为包含原始文档中每个字段/值对的元素的数组。返回数组中的每个元素都是一个包含两个字段 k 和 v 的文档。 在$project阶段中仅使用运算符运行管道
db.coll.aggregate([
{ "$project": {
"keys": { "$objectToArray": "$$ROOT" }
} }
])
Run Code Online (Sandbox Code Playgroud)
产量
{
"_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"
}
}
]
}
Run Code Online (Sandbox Code Playgroud)
的$filter操作者充当由所述产生的阵列的过滤机制$objectToArray操作,工程通过选择基于成为查询中指定的条件返回阵列的一个子集。
考虑以下管道,它返回与条件匹配的键/值对数组 { "samekeyA": "value1" }
db.coll.aggregate([
{ "$project": {
"keys": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": {
"$eq": [
"$$el.v.samekeyA",
"value1"
]
}
}
}
} }
])
Run Code Online (Sandbox Code Playgroud)
这产生
{
"_id" : 1,
"keys" : [
{
"k" : "key1",
"v" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
]
}
Run Code Online (Sandbox Code Playgroud)
这将从上面的过滤数组转换
[
{
"k" : "key1",
"v" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
]
Run Code Online (Sandbox Code Playgroud)
使用动态键转到原始文档
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
Run Code Online (Sandbox Code Playgroud)
所以运行管道
db.coll.aggregate([
{ "$project": {
"key": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": {
"$eq": [
"$$el.v.samekeyA",
"value1"
]
}
}
}
}
} }
])
Run Code Online (Sandbox Code Playgroud)
会产生
{
"_id" : 1,
"key" : {
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
}
Run Code Online (Sandbox Code Playgroud)
这会将过滤后的动态密钥文档提升到顶级并替换所有其他字段。该操作替换输入文档中的所有现有字段,包括该_id字段。
本质上,这转换了上述文档
{
"_id" : 1,
"key" : {
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
}
Run Code Online (Sandbox Code Playgroud)
到所需的最终输出
{
"key1" : {
"samekeyA" : "value1",
"samekeyB" : "value2"
}
}
Run Code Online (Sandbox Code Playgroud)