从嵌入文档生成的字段名称。我疯了吗?

时间:2017-04-08 22:08:21

标签: arrays mongodb

以下设计决策存在哪些潜在问题?

假设您有一个MongoDB集合,对于每个文档,您希望在其中一个嵌入字段中存储许多文档。想想一种一对多的关系。

出于不同的原因,要避免使用数组,这意味着集合中的文档将不会像这样

{
    p: 1,
    q: [
        { k1: 1, k2 : "p", x: "aaa" },
        { k1: 2, k2 : "b", x: "bbb" }
    ]
}

相反,我选择执行以下操作

{
    p: 1,
    q: {
        KEY1 : { k1: 1, k2 : "a", x: "aaa" },
        KEY2 : { k1: 2, k2 : "b", x: "bbb" }
    }
}

其中KEY1和KEY分别是代表文档{k1: 1, k2 : "a" }{k1: 2, k2 : "b"}的唯一字符串。

只要表示是唯一的,就可以通过多种方式计算这种字符串。例如,{k1: 1, k2 : "a"}{k2 : "a" , k1: 1}应该具有相同的字符串,并且应该与{k2 : "a" , k1: "1"}的字符串不同。它应该考虑到某些ki的值也可以是文档。

顺便说一句,我不能使用哈希函数来计算KEY,因为我需要存储所有文档。

(如果你还在这里,我没有使用数组的原因是因为我在向字段q添加文档时需要原子性,我需要修改字段x,尽管k1已添加k2q未添加到$addToSet。此设计基于以下问题:MongoDB arrays - atomic update or push element_id仅适用于整个文档)< / p>

两个可能的问题来源:

  • 可能的KEY数量会快速增长。 (虽然在我的情况下它应该在数千人之下)
  • 键本身可能是非常长的字符串。它会降低性能吗?

技术观点

关于可行性,documentation of MongoDB仅表示字段不能为$,且不能包含字符.nullnullBSON spec仅表示它应该是修改后的UTF-8字符串,不包括{ p: 1, q: { { k1: 1, k2 : "a" } : { x: "aaa" }, { k1: 2, k2 : "b" } : { x: "bbb" } } }

我已经完成了以下操作,但MongoDB抱怨密钥应该是不可变的:

$group

但是,您可以在聚合框架中使用运算符{k1: 1, k2 : "a" }使用相关的类似表示法。只是类似的表示法:你不能将这些东西保存到集合中。

如果文档k1直接存储在集合中,意味着没有嵌入,那么整个想法似乎都没有必要。在这种情况下,我只需将k2{ p: 1, q: _id_in_Many } 设置为唯一索引,然后使用update / upsert插入而不重复。所有这些过度杀伤是因为它不能在数组中。实际上,似乎数组几乎就像一个集合,其中_id是数组中的位置。如果我在这一段中没有错,那么在顶级集合中可以表示的内容应该可以在嵌入式文档中表示。

编辑:如何使用集合代替嵌入? (由@hd评论后编辑)

我的最终目标是与原子性建立一对多关系,尤其是在更新多方面时。

让我们探讨使用单独的文件来表示一对多关系的想法。这意味着两个集合:

收藏cOne

{
    id: ...,
    p: 1,
    q: { k1: 1, k2 : "p" },
    x: "aaa",
}

收藏cMany

{p: 1, q: 1}

在这种情况下,我应该在cMany + updateOne / upsert中使用唯一索引来确保唯一性{k1: ..., k2 : ...}。但是,索引每个条目的限制为1024字节,但{ id: ..., p: 1, key: KEY1, k1 : 1, k2 : "p" , x: "aaa", } 可能超出它,特别是如果值包含utf-8字符串。

如果我仍然使用按照说明生成的KEY,就像这样

{p : 1, key: 1}

然后,对于索引{k1: ..., k2 : ...},达到1024字节限制的可能性仍然存在。我得说,我不认为k1远远超过1k。我知道每个文件的16b限制。

也许有一种原则性的方法让一个字段上的集合唯一,哪些值会让索引条目超过1k,但我找不到它。 upsert的mongo文档说“要避免多次upsert,请确保过滤字段是唯一索引的。”

相反,似乎对字段名称的长度没有官方限制,字段分配应该像任何其他文档更新一样唯一。

编辑2:数组和文档是否比集合更强大? (由@hd评论后编辑)

由于我没有找到一种方法将一个任意文档添加到Collection中,保留了唯一性,我们可以认为Document和Arrays比Collections更强大,更独特。文档字段名称是唯一的,并且数组至少支持$addToSet,如果我只有k2x但不可变{{1}},那就足够了。

0 个答案:

没有答案