MongoDB:查找具有未知键的对象中给定字段值的文档

3
我正在制作一个关于论文/论点的数据库。它们与其他论点有关联,我已经将它们放在了一个对象中,并使用 动态密钥 进行了标记,这个密钥是完全随机的。
{
    _id : "aeokejXMwGKvWzF5L",
    text : "test",
    relations : {
        cF6iKAkDJg5eQGsgb : {
            type : "interpretation",
            originId : "uFEjssN2RgcrgiTjh",
            ratings: [...]
         }
    }
}

如果我只知道type的值,我能找到这个文档吗?也就是说,我想做像下面这样的事情:

db.theses.find({relations['anything']: { type: "interpretation"}}})

如果`relations`是一个数组,那么使用位置操作符就可以轻松完成此操作。但是,由于Mongo不支持这些更新,因此我无法对`ratings`中的对象进行更改。我在这里询问是否可以避免更改数据库结构。
1个回答

2
尽管您似乎是因为使用嵌套数组时出现更新问题而接近这个结构,但实际上通过做一些不受支持的操作只会引起另一个问题,即标准查询运算符中没有“通配符”概念来搜索未指定的键。
您真正可以搜索此类数据的唯一方法是在服务器上使用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" })

当然,位置变量 $ 操作符现在可以与更扁平的结构一起使用:
db.theses.update(
    { "relationsRatings.ratingId": 1 },
    { "$set": { "relationsRatings.$.ratingScore": 7 } }
)

当然,这意味着每个“ratings”值的“related”数据都会被复制,但这通常是按匹配位置更新的代价,因为这只支持单层数组嵌套。
因此,您可以强制逻辑与其结构匹配,但这不是一个好主意,会导致性能问题。然而,如果您的主要需求是更新“ratings”信息而不仅仅是附加到内部列表,那么更扁平的结构将更有益处,并且当然会更快地搜索。

非常感谢您提供如此详细的答案!看来将JavaScript代码插入MongoDB对于我的目的来说需要太长时间,但知道这是可能的很酷。 - Carl Jakobsson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接