2013-03-02 33 views
-1

考虑以下数据结构对于一次存储在数据库系统(rdbms或nosql)中的数据,QUERY会更好吗?元数据字段中的字段是用户定义的,因用户而异。可能的值是字符串,数字,“日期”或甚至数组。mongodb(或其他nosql dbs)是以下场景的最佳解决方案吗?

var file1 = { 
    id: 123, name: "mypicture", owner: 1 
    metadata: { 
     people: ["Ben", "Tom"], 
     created: 2013/01/01, 
     license: "free", 
     rating: 4 
     ... 
    }, 
    tags: ["tag1", "tag2", "tag3", "tag4"] 
} 

var file2 = { 
    id: 155, name: "otherpicture", owner: 1 
    metadata: { 
     people: ["Tom", "Carla"], 
     created: 2013/02/02, 
     license: "free", 
     rating: 4 
     ... 
    }, 
    tags: ["tag4", "tag5"] 
} 

var file1OtherUser = { 
    id: 345, name: "mydocument", owner: 2 
    metadata: { 
     autors: ["Mike"], 
     published: 2013/02/02, 
     …  
    }, 
    tags: ["othertag"] 
} 

我们的用户应该有搜索/过滤文件的功能:

  • 用户1:显示所有文件,其中“汤”是“人”的阵列
  • 用户1:显示全部创建“2013/01/01至2013/02/01之间的文件”
  • 用户1:在“2012”中标注为“重要”
  • ...

结果应该像这样,你可以在OS X做智能文件夹进行过滤。各个元数据字段在文件上传/存储之前定义。但是之后它们也可能改变,例如用户1可以将元数据字段“people”重命名为“cast”。

+0

如果这些字段是可变的,那么您将无法有效地对字段建立索引,因为mongodb集合中的索引总数不仅有64个,而且还有一个总体建议对于MongoDb,您可能需要将结构扁平化以在键入或索引的集合中具有键和值。你有没有考虑过如何用数据做MapReduce? – WiredPrairie 2013-03-02 13:08:00

+0

我提出一个类型化索引的原因是,所有的特定索引值都是相同的。 – WiredPrairie 2013-03-02 13:10:54

回答

0

正如@WiredPrairie表示,metadata场看变量中的领域,也许取决于用户输入什么它支持:

用户1可以重命名元数据字段“人”,以“铸造” 。

MongoDB的,由此你刚才说,在metadata每一个新的领域被添加到复合索引,但是你可以做一个键值式结构,像这样不能创建变量指标:

var file1 = { 
    id: 123, name: "mypicture", owner: 1 
    metadata: [ 
     {k: people, v:["Ben", "Tom"]}, 
     {k: created, v:2013/01/01}, 
    ], 
    tags: ["tag1", "tag2", "tag3", "tag4"] 
} 

也就是说这样做的一种方法,允许您在metadata字段内动态索引kv。然后你会这样查询:

db.col.find({metadata:{$elemMatch:{k:people,v:["Ben"]}}}) 

但是这确实会引入另一个问题。 $elemMatch适用于顶层,而不是嵌套的元素。想象一下,你想找到这里的“本”是people之一的所有文件,则不能使用$elemMatch这里,所以你必须做的:

db.col.find({metadata.k:people,metadata.v:"Ben"}) 

该查询的迫在眉睫的问题是这样的MongoDB查询。当它查询metadata字段时,将会说:其中“k”的一个字段等于“people”并且字段“v”等于“Ben”

由于这是一个多值字段,所以即使“Ben”不在人群列表中,因为他存在于metadata的另一个字段中,您实际上会挑出错误的文档;即,该查询将回暖:

var file1 = { 
    id: 123, name: "mypicture", owner: 1 
    metadata: [ 
     {k: people, v:["Tom"]}, 
     {k: created, v:2013/01/01}, 
     {k: person, v: "Ben"} 
    ], 
    tags: ["tag1", "tag2", "tag3", "tag4"] 
} 

解决这个问题的唯一现实的办法就是关因素的动态领域到另一个集合,其中你没有这个问题。

虽然这会产生一个新问题,但您无法再单次往返获取完整文件,也无法一次性聚合文件行及其用户定义的字段。总而言之,通过这个东西你会失去很多能力。

话虽这么说,你仍然可以执行相当多的疑问,即:

  • 用户1:显示所有文件,其中“汤”是“人”的阵列
  • 用户1:显示所有文件“创建“2013年1月1日至2013年2月1日之间
  • 用户1:显示”许可“”免费“和”评级“更大的所有文件2
  • 用户2:显示” 2012“并标记为”重要“

所有这些仍然可以用这个模式。

至于哪个更好-RDBMS或NoSQL;这里很难说,如果做得对,我可以说两者都可以相当好,以查询这种结构。

+0

感谢您的回答。我如何确定元数据字段的类型(字符串,数字,日期)以便在gui中正确显示它,例如日期选择器?我想我需要将这个类型与每个条目一起存储,对吧? 我想听到更多的意见,特别是喜欢关系解决方案的人。 (到目前为止,我还是不会回答这个问题。) – joafeldmann 2013-03-02 14:37:36

+0

@joafeldmann这取决于你如何在你的界面中使用它,你可能会被要求,但更多的是你测试返回的字段的值,看看它是什么。 – Sammaye 2013-03-02 14:40:27