社交应用程序的多对多关系:像Neo4j这样的Mongodb或图形数据库

时间:2012-02-14 20:56:52

标签: mongodb many-to-many graph-databases

我试图了解Mongodb中的嵌入但是找不到足够好的文档。不建议链接,因为写入在文档中不是原子的,并且还有两个查找。有人知道如何解决这个问题,或者你建议我去看看像neo4j这样的图表。

我正在尝试构建一个需要多对多关系的应用程序。为了解释,我将以图书馆为例。它可以根据他的朋友正在阅读的书籍以及用户正在阅读的邻居(像头脑一样)来向用户推荐书籍。

有用户和书籍。用户借书和拥有其他用户的朋友

  1. 鉴于用户,我需要他正在阅读的所有书籍以及相互的数量 这本书的朋友
  2. 鉴于一本书,我需要所有阅读它的人。可以给 一个用户A,这将返回人们阅读的书 和用户A的朋友。这是相互的友谊
  3.   

    用户= [

           { name: 'xyz', 'id':'000000', friend_ids:['949583','958694']}
    
           { name: 'abc', 'id':'000001', friend_ids:['949582','111111']}
    
          ]
    
         

    书籍= [

          {'book':'da vinci code', 'author': 'dan brown', 'readers'=['949583', '000000']}
    
          {'book':'iCon', 'author': 'Young', 'readers'=['000000', '000001']}
    
          ]
    

    如上所示,如果我采用mongo DB,我通常需要两个文件,因为我可以双向查找。将文档复制(嵌入)到另一个文档可能会导致大量的重复(这些模式可以存储比显示的信息更多的信息)。

    我是否正确建模数据?这可以在mongodb中有效地完成,还是应该查看图dbs。

2 个答案:

答案 0 :(得分:6)

免责声明:我为Neo4j工作

从您的大纲,要求和数据类型看,您的应用程序似乎是图形数据库的甜点。

我建议你用图表数据库快速加速,看看它是怎么回事。

  • 没有重复
  • 您有原子操作的交易
  • 以下链接是自然操作
  • 本地查询(例如来自用户或书籍)便宜且快速
  • 您可以使用最短路径等图形算法来查找有关数据的有趣信息
  • 建议和类似操作对图数据库来说是很自然的

一些问题:

  • 你为什么首先选择MongoDB?
  • 您使用的是哪种实施语言?

答案 1 :(得分:5)

上面的基本架构提案适用于MongoDB,并提出一些建议:

  1. 将整数用于标识符,而不是字符串。 MongoDB通常会更紧凑地存储整数(它们总是8个字节,而字符串的存储大小将取决于字符串的长度)。您可以使用findAndModify来模拟唯一的序列生成器(如某些关系数据库中的auto_increment) - 有关如何完成此操作的示例,请参阅Mongoengine's SequenceField。您还可以使用始终为12个字节的ObjectIds,但实际上保证是唯一的,而无需在数据库中存储任何协调信息。
  2. 您应该使用_id字段而不是id,因为此字段始终存在于MongoDB中,并且在其上创建了默认的唯一索引。这意味着您的_id始终是唯一的,_id的查询速度非常快。
  3. 你是对的,使用这种模式需要多个find(),并且每次都会产生网络往返开销。但是,对于上面建议的每个查询,您需要的查找次数不超过2次,并结合一些简单的应用程序代码:

    1. “鉴于用户,我需要他正在阅读的所有书籍以及该书的共同朋友数量”

      一个。查找有问题的用户,然后b。使用db.books.find({_id: {$in: [list, of, books, for, the, user]}})查询图书集,然后是c。对于每本书,为该书的读者和用户的朋友计算一组联合
    2. “鉴于一本书,我需要所有阅读它的人。”

      a。查阅有问题的书,然后b。再次使用$in
    3. db.users.find({_id: {$in: [list, of, users, reading, book]}})查找正在阅读该图书的所有用户
    4. “可以给用户A,这将返回人们阅读书籍和用户A的朋友。”

      a。查找有问题的用户,然后b。查看有问题的书,然后是c。计算用户朋友和书籍读者的集合联盟
    5. 我应该注意,如果您有很长的列表,$in可能会很慢,因为它实际上相当于对N个项目列表进行N次查找。但是,服务器会为您执行此操作,因此它只需要一次网络往返而不是N.

      作为对某些查询使用$in的替代方法,您可以在数组字段上创建索引,并在集合中查询数组中具有特定值的文档。例如,对于上面的查询#1,您可以执行以下操作:

      // create an index on the array field "readers"
      db.books.ensureIndex({readers: 1})
      
      // now find all books for user whose id is 1234
      db.books.find({readers: 1234})
      

      这称为multi-key index,在某些情况下效果可能优于$in。您的确切经验将根据文档数量和列表大小而有所不同。