如何更新包含点的嵌套键?

问题描述 投票:0回答:1

在这样的文档中:

[
  {
    a: "",
    b: 1,
    "createdAccounts": {
      "[email protected]": {
        "id": ["a", "b", "c"]
      }
    }
  }
]

我正在查询电子邮件:

    const email = "[email protected]"
    let account = await db.collection("users").aggregate(
    [
        {
            "$project": {
                "createdAccounts": {
                    "$objectToArray": "$createdAccounts"
                }
            }
        },
        {
            "$match": {
                "createdAccounts.k": email
            }
        },
        {
            "$project": {
                "createdAccounts": {
                    "$arrayToObject": "$createdAccounts"
                }
            }
        }
    ]).toArray().then(results =>
    {
        const document = results[0];
        if (document && document.createdAccounts)
            return document.createdAccounts[email];        
        return null; 
    })

我想知道是否有“更好的方法”来查询电子邮件,我使用聚合,因为搜索的键可以在其路径中包含一个点(

.

在这种情况下,这个:

const email = "[email protected]"
let account = await db.collection("users").findOne({ "createdAccounts.email": email });

不起作用。

使用我得到的聚合查询作为响应:

"[email protected]": {
    "id": ["a", "b", "c"]
}

假设我需要修改

id
数组,因为它的内部包含一个点 (
.
) 我找不到如何更新它。

另外,update方法会连接数组还是覆盖数组?

javascript mongodb mongodb-query
1个回答
0
投票

首先,您确实应该为此使用属性模式。 Mongo 不能很好地处理“未知键”,这与 JS(和 Python)不同,您可以在 JS(和 Python)中迭代键和值。

此管道将在

id
字段中附加一个元素,用于匹配的电子邮件。

db.users.aggregate([
  {
    "$project": {
      "createdAccounts": {
        "$objectToArray": "$createdAccounts"
      }
    }
  },
  {
    "$match": {
      // replace with the `email` you want to match
      "createdAccounts.k": "[email protected]"
    }
  },
  {
    "$set": {
      "createdAccounts.v.id": {
        "$concatArrays": [
          // unclear why I need this "first" but the
          // concat produces an extra array if I don't
          { "$first": "$createdAccounts.v.id" },
          ["X"]  // <-- put the element you want to add
        ]
      }
    }
  },
  {
    "$set": {
      "createdAccounts": {
        "$arrayToObject": "$createdAccounts"
      }
    }
  },
  {
    "$merge": {
      "into": "collection",
      "on": "_id",
      "whenMatched": "merge",
      "whenNotMatched": "discard"
    }
  }
])

请注意,在 Mongo Playground 中,它只会根据管道结果显示文档。合并结果可以通过查看集合中更新的文档来看到。

结果:

{
  "_id": 1,
  "a": "",
  "b": 1,
  "createdAccounts": {
    "[email protected]": {
      "id": [
        "a",
        "b",
        "c",
        "X"
      ]
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.