-1

考虑以下数据结构,一旦存储在数据库系统(rdbms 或 nosql)中,查询数据会更好吗?元数据字段中的字段是用户定义的,并且会因用户而异。可能的值是字符串、数字、“日期”甚至数组。

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:显示所有“许可”“免费”和“评级”大于 2 的文件
  • 用户 2:显示“2012”中“已发布”并标记为“重要”的所有文件
  • ...

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

4

1 回答 1

0

正如@WiredPrairie 所说,字段中的metadata字段看起来是可变的,可能取决于用户输入的内容,受以下支持:

用户 1 可以将元数据字段“people”重命名为“cast”。

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"]
}

这是执行此操作的一种方法,允许您在字段kv动态索引两者。metadata然后你会这样查询:

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

然而,这确实引入了另一个问题。$elemMatch适用于顶层,而不是嵌套元素。想象一下,您想查找“Ben”是其中之一的所有文件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/01/01 和 2013/02/01 之间“创建”的所有文件
  • 用户 1:显示所有“许可”“免费”和“评级”大于 2 的文件
  • 用户 2:显示“2012”中“已发布”并标记为“重要”的所有文件

使用此模式,所有这些仍然是可能的。

至于哪个更好——RDBMS还是NoSQL;在这里很难说,我想说如果做得好,在查询这个结构时两者都可以很好。

于 2013-03-02T13:31:57.520 回答