Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB中具有动态键字段的JSON模式_Mongodb_Jsonschema - Fatal编程技术网

MongoDB中具有动态键字段的JSON模式

MongoDB中具有动态键字段的JSON模式,mongodb,jsonschema,Mongodb,Jsonschema,想要对mongodb集合中存储的对象提供i18n支持吗 目前我们的模式如下: { _id:“id” 姓名:“姓名” 本地化:[{ 兰:“恩,我们”, 姓名:“英语姓名” }, { lan:“zh TW”, 姓名:“繁体中文姓名” }] } 但是我的想法是“lan”字段是唯一的,我可以把这个字段作为一个键来使用吗,所以结构会很简单 { _id:“id” 姓名:“姓名” 本地化:{ “en US”:“英语名称”, “zh TW”:“姓名用繁体中文” } } 这将更整洁,更容易解析(只需本地化[语

想要对mongodb集合中存储的对象提供i18n支持吗

目前我们的模式如下:

{
_id:“id”
姓名:“姓名”
本地化:[{
兰:“恩,我们”,
姓名:“英语姓名”
}, {
lan:“zh TW”,
姓名:“繁体中文姓名”
}]
}
但是我的想法是“lan”字段是唯一的,我可以把这个字段作为一个键来使用吗,所以结构会很简单

{
_id:“id”
姓名:“姓名”
本地化:{
“en US”:“英语名称”,
“zh TW”:“姓名用繁体中文”
}
}
这将更整洁,更容易解析(只需本地化[语言]就可以得到我想要的特定语言的值)


但问题是:这是在MongoDB中存储数据的良好实践吗?如何通过json模式检查?

显然,第二个模式示例更适合您的任务(当然,如果
lan
字段如您所述是唯一的,这对我来说也是正确的)

字典/关联数组/映射/无论它在您的语言中被称为什么,
获取元素要比扫描整个值数组便宜得多(在当前情况下,从存储大小的角度来看,它也非常有效)(请记住,所有字段都按原样存储在MongoDB
中,因此每个记录都保存json字段的整个键名,而不是它的表示或索引或其他内容)

我的经验表明,MongoDB已经足够成熟,可以用作应用程序的主存储,即使是在高负载情况下(无论它是什么意思;)),主要问题是如何对抗数据库级锁(好吧,我们将等待承诺的表级锁,我希望它会加快MongoDB的速度),但如果您的MongoDB集群构建得不好,则可能会丢失数据(深入互联网上的文档和文章以获取更多信息)


至于模式检查,您必须在插入记录之前通过应用程序端的编程语言进行检查,是的,这就是为什么Mongo被称为无模式的

将值作为键不是一种好的做法。语言代码是值,正如您所说,您无法根据模式验证它们。它会再次进行查询这是不可能的。例如,您无法确定是否有“nl nl”的语言翻译,因为您无法与关键字进行比较,也不可能轻松为其编制索引。您应该始终具有描述性关键字

但是,正如您所说的,将语言作为键可以更轻松地提取数据,因为您可以通过
['nl-nl']
(或您的语言语法)访问数据

我建议另一种模式:

{
    your_id: "id_for_name"
    lan: "en-US",
    name: "name_in_english"
}
{
    your_id: "id_for_name"
    lan: "zh-TW",
    name: "name_in_traditional_chinese"
}
现在您可以:

  • {your_id:1,lan:1}
    上设置索引,以便快速查找
  • 单独查询每个翻译并仅获取该翻译:
    db.so.find({your_id:'id_代表_name',lan:'en-US'})
  • 使用相同索引查询每个id的所有版本:
    db.so.find({your_id:id\u for_name})
  • 而且更容易更新特定语言的翻译:

    db.so.update(
        { your_id: "id_for_name", lan: 'en-US' }, 
        { $set: { name: "ooga" } } 
    )
    

这两个点在您建议的模式中都是不可能的。

在这种情况下,对象必然比数组更好:支持向上插入到集合中。例如,如果您希望将具有
名称的项更新为具有
val
100,或者如果不存在这样的项,则插入这样一个项,则全部在一个原子中完成对于数组,您必须执行两个操作之一

{ _id: 'some-id', itemSet: [ { name: 'an-item', val: 123 } ] }
你会有命令的

// Update:
db.coll.update(
  { _id: id, 'itemSet.name': 'item1' },
  { $set: { 'itemSet.$.val': 100 } }
);

// Insert:
db.coll.update(
  { _id: id, 'itemSet.name': { $ne: 'item1' } },
  { $addToSet: { 'itemSet': { name: 'item1', val: 100 } } }
);
您必须首先查询,以了解需要提前查询哪些内容,这会加剧竞争条件,除非您实现一些版本控制

db.coll.update({
  { _id: id },
  { $set: { 'itemSet.name': 'item1', 'itemSet.val': 100 } }
});
如果这是一个用例,那么您应该使用对象方法。一个缺点是查询特定名称需要扫描。如果也需要扫描,您可以添加一个单独的数组专门用于索引。这是MongoDB的一个折衷方案。Upserts将成为

db.coll.update({
  { _id: id },
  { 
    $set: { 'itemSet.name': 'item1', 'itemSet.val': 100 },
    $addToSet: { itemNames: 'item1' } 
  }
});
然后,查询将简单地

db.coll.find({ itemNames: 'item1' })
(注意:
$
位置运算符不支持数组加高。)

胡说八道。“单独查询翻译”:
db.so.find({'localization.lan':'en-US'})
(这里可以使用索引),或
db.so.find({'localization.en-US':{$exists:true}})
“查询每个id的所有翻译”:
db.so.find({{u-id:'id'})
如果你只需要翻译,请添加一个字段说明符。“更新特定翻译”:
db.so.Update({u-id:'id','localization.lan':'en-US'},{$set:{'localization.$.name':'ooga'})
db.so.Update({u-id:'id','localization.en-US':{$exists:true},{$set:{'localization.en-US.name':'ooga'})
。每种方法都有其独特的特点;没有一种是“不良做法”。