MongoDB架构结构和查询

时间:2012-08-08 14:54:27

标签: mongodb

我刚刚进入mongoDB开发阶段。使用shell,我可以将以下内容存储到名为vrm的集合中:

w = {
  westpalm :{
    users : [
      {pkanane : {names : {lastName : "Anane", otherNames : "Papa Kwame"}}, contacts : {}, authorization : {}},
      {csquire : {}},
      {oman : {}}
    ],
    customers : [], 
    vehicles : [], 
    settings : []

  }  
}

a = {
  wuduwudu :{
    users : [
      {pkanane : {names : {lastName : "Anane", otherNames : "Papa Kwame"}}, contacts : {}, authorization : {}},
      {zkenpachi : {}}
    ],
    customers : [], 
    vehicles : [], 
    settings : []

  }  
}

然后我保存如下db.vrm.save(a)和db.vrm.save(w)

Q1。我想建模的是 2 公司 wuduwudu westpalm ,每家公司都有用户客户车辆等。每个用户都有一个名称 - 由 lastName otherNames 组成, 联系人等。这是建模数据要求的好方法吗?

Q2。如何检索用户的 otherNames pkanane

由于

1 个答案:

答案 0 :(得分:2)

我将在原始架构的上下文中首先解决您的第二个问题。使用用户名作为索引将使查询变得更加困难,因为您将使用可变字段名称。同样,在用户对象中索引这样的字段将不会缩放,因为每个不同的字段路径将需要其自己的索引。也就是说,查询效率低下是可能的:

db.companies.drop()
db.companies.insert({
    _id: "wuduwudu",
    users: [
        { pkanane: { fullName: "Papa Kwame" } }
    ]
});
db.companies.find({ "users.pkanane": { $exists: true }}, { "users.pkanane.fullName": 1 });
{ "_id" : "wuduwudu", "users" : [ { "pkanane" : { "fullName" : "Papa Kwame" } } ] }

改进是使users成为嵌入式用户对象的数组。使用此模式,您可以利用users.username字段上的multikey indexes,Mongo会为每个文档索引数组中的所有用户名。

db.companies.drop()
db.companies.insert({
    _id: "westpalm",
    users: [
        { username: "pkanane", fullName: "Papa Kwame" }
    ]
});
db.companies.find({ "users.username": "pkanane" }, { "users.pkanane.fullName": 1 });
{ "_id" : "wuduwudu", "users" : [ { "pkanane" : { "fullName" : "Papa Kwame" } } ] });

要重新思考您的架构,我首先要看一下公司和用户对象结构。如上所述,动态字段名称不适用于索引。我建议不要使用公司名称作为文档中唯一的顶级密钥。您可以将其用于_id,就像我在上面的示例中所做的那样,或者依赖MongoDB生成ObjectId并将公司名称存储在userscustomers旁边的自己的字段中,等

通常,用户是大多数应用程序中的第一类对象。如果您在公司的上下文之外使用和编辑它们,我会考虑将它们存储在自己的集合中,而是在公司文档中保留一组用户ID。另外,在您自己的示例中,您在两家公司之间复制了“pkanane”。这是另一种气味,您可能最好在其自己的集合中引用用户文档。客户,车辆和设置可能不是您应用程序中的第一类对象,因此嵌入它们可能更合适。 MongoDB文档中的Schema Design条目是一个很好的起点(我已经链接到最佳实践列表)。

嵌入式文档的另一个挑战可能是您的应用程序允许单独编辑单个嵌入式文档。这通常用于在用户文档中嵌入地址簿并提供“编辑您的地址”表单的模式。使用可以更改的对象的数组位置是不可靠的,因为在对象上具有不可变字段。在我上面的第二个代码示例中使用模式,如果它是不可变的,我们可以使用username。或者,我们可以在每个嵌入的文档上存储唯一的ObjectId并引用它。

在最后一个注释中,您最终可能会将用户移动到他们自己的集合中,但这些建议对于您在公司中嵌入的任何内容都是有效的。

相关问题