虽然由于使用嵌套数组时的更新问题,您似乎已经接近了这种结构,但您确实只是通过执行其他不受支持的操作而引起了另一个问题,那就是没有 "通配符” 使用最佳标准查询运算符搜索未指定键的概念。
真正搜索此类数据的唯一方法是使用服务器上的 JavaScript 代码使用 $where 遍历键。这显然不是一个真正的好主意,因为它需要蛮力评估,而不是使用索引等有用的东西,但可以按如下方式处理:
db.theses.find(function() {
var relations = this.relations;
return Object.keys(relations).some(function(rel) {
return relations[rel].type == "interpretation";
});
))
虽然这将从集合中返回那些包含所需嵌套值的对象,但它必须检查集合中的每个对象才能进行评估。这就是为什么只有在与可以直接使用索引而不是作为集合中对象的硬值的东西配对时才应该使用这种评估。
更好的解决方案是考虑重构数据以利用搜索中的索引。如果需要更新“评级”信息,则基本上“展平”结构以将每个“评级”元素视为唯一的数组数据:
{
"_id": "aeokejXMwGKvWzF5L",
"text": "test",
"relationsRatings": [
{
"relationId": "cF6iKAkDJg5eQGsgb",
"type": "interpretation",
"originId": "uFEjssN2RgcrgiTjh",
"ratingId": 1,
"ratingScore": 5
},
{
"relationId": "cF6iKAkDJg5eQGsgb",
"type": "interpretation",
"originId": "uFEjssN2RgcrgiTjh",
"ratingId": 2,
"ratingScore": 6
}
]
}
现在搜索当然很简单:
db.theses.find({ "relationsRatings.type": "interpretation" })
当然,positional $ 运算符现在可以与更扁平的结构一起使用:
db.theses.update(
{ "relationsRatings.ratingId": 1 },
{ "$set": { "relationsRatings.$.ratingScore": 7 } }
)
当然,这意味着为每个“评分”值复制“相关”数据,但这通常是按匹配位置更新的成本,因为这仅支持单级数组嵌套。
因此,您可以强制逻辑与您的结构方式相匹配,但这样做并不是一个好主意,并且会导致性能问题。但是,如果您在这里的主要需求是更新“评分”信息,而不是仅仅附加到内部列表,那么更扁平的结构将有更大的好处,当然搜索速度也会更快。