2011-12-14 139 views
3

我想我的音乐应用程序的模式设计有问题。MongoDB架构设计。不能得到我想要的

我有3系列:ArtistsTracksAlbums。 和3类:artists,从artistsalbumstracks

文件:

  [_id] => MongoId Object 
      (
       [$id] => 4ee5bbfd615c219a07000000 
      ) 
     [freeze] => false, 
     [genres] => Array, 
     [hits] => 0, 
     [name] => Sarya Al Sawas, 
     [pictures] => Array, 

文件从albums

 [_id] => MongoId Object 
      (
       [$id] => 4ee88308615c218128000000 
      ) 

     [name] => Sabia 
     [slug] => wafiq-habib-ft-sarya-al-sawas-sabia 
     [year] => 1999 
     [genres] => Array, 
     [pictures] => Array, 
     [artists] => Array 
      (
       [0] => MongoId Object 
        (
         [$id] => 4ee34a3b615c21b624010000 
        ) 

       [1] => MongoId Object 
        (
         [$id] => 4ee5bbfd615c219a07000000 
        ) 

      ) 

文件从tracks

  [_id] => MongoId Object 
      (
       [$id] => 4ee8a056615c21542a000000 
      ) 

     [name] => Bid Ashok 
     [slug] => wafiq-habib-ft-sarya-al-sawas-bid-ashok 
     [genres] => Array, 
     [file] => /m/tracks/t.4ee8a05540c624.04707814.mp3, 
     [freeze] => false, 
     [hits] => 0, 
     [duration] => 303, 
     [albums] => Array 
      (
       [0] => MongoId Object 
        (
         [$id] => 4ee5cbc3615c216509000000 
        ) 

      ) 

     [artists] => Array 
      (
       [0] => MongoId Object 
        (
         [$id] => 4ee5bbfd615c219a07000000 
        ) 

       [1] => MongoId Object 
        (
         [$id] => 4ee34a3b615c21b624010000 
        ) 

      ) 
首先是

是好的模式设计??! 我以这种方式设计了这种模式,因为有多对多的关系 有时曲目有2位艺术家,专辑有2位艺术家。

无论如何,我有问题查询附加到特定曲目的专辑。

可以说我是艺术家页面

  1. 我需要得到所有艺术家的专辑上,并跟踪,所以我这样做:

    $cursors = array(
        'albums' => $this->albums->find(array('artists' => $artist->_id))->sort(array('_id' => -1)), 
        'tracks' => $this->tracks->find(array('artists' => $artist->_id))->sort(array('_id' => -1)), 
        'clips' => $this->clips->find(array('artists' => $artist->_id))->sort(array('_id' => -1)) 
    ); 
    foreach($cursors as $key => $cursor) { 
        foreach($cursor as $obj) { 
         $obj['name'] = ($this->lang->get() != 'ar' ? $obj['translated']['name'] : $obj['name']); 
         $obj['by'] = $this->artists()->get($obj['artists'])->toString('ft'); 
         ${$key}[] = $obj; 
        } 
    } 
    
  2. 我需要的所有曲目循环并得到他们的专辑名称可以说这个艺术家有3000首曲目 我认为它会很慢....

所以我的问题是:这是一个很好的架构设计

回答

3

那么,这是一个非常关系的问题,而使用非关系数据库来解决这个问题需要一些努力。总的来说,我认为你的模式设计很好。你要描述的是“N + 1问题”,因为你必须为N个对象进行N + 1个查询(在你的情况下,它更复杂,但我想你会明白) 。

一些补救措施:

  • 可以使用$in运算符查找例如某位艺术家的所有曲目:

    db.tracks.find({"artists" : { $in : [artist_id_1, artist_id_2, ...] } }); 
    

    如果艺术家的阵列巨大的增长这是不行的,但几百,也许一千应该正常工作。确保artists已编入索引。

  • 您可以非常频繁地将一些需要的信息去标准化。例如,您可能想要经常显示曲目列表,因此将艺术家的名称复制到每个曲目是有意义的。反规范化主要取决于您想要从最终用户的角度实现的目标。您可能不希望将每个艺术家的姓名全部存储,但只有前50个字符,因为UI在总览中不会显示更多内容。实际上,你已经对一些数据进行了非规范化处理,例如专辑中的艺术家id(这些数据是多余的,因为你可以通过轨道获取它们)。这使得查询更容易,但它会更加重写。更新是丑陋的,因为你必须确保它们通过系统传播。

  • 在某些情况下,在客户端(!)而不是服务器上“加入”可能有意义。这并不适合你的问题,但值得注意的是:假设你有一个朋友列表。现在,当服务器显示它们时,服务器必须查看每个朋友的名字。相反,它可以为您提供查找表ID /朋友,并且服务器仅为ID提供服务。有些JavaScript可以用客户端缓存中的实名替换ID。

+0

谢谢@mnemosyn我把专辑链接回艺术家的原因是因为我需要他们在那里,我并不总是想要得到曲目有时我只想要专辑,艺术家直接在轨道文件上的名字是一个不错的主意,我试过它它的作品不错,但我想看看是否有人想出了一个更好的想法.... – Pinokyo 2011-12-14 15:24:03