【问题标题】:MongoDB Schema Design . can't get what i wantMongoDB 架构设计。得不到我想要的
【发布时间】:2012-01-20 07:24:03
【问题描述】:

我认为我的音乐应用程序的架构设计存在问题。

我有 3 个集合:ArtistsTracksAlbums。 和 3 个类:artistsalbumstracks

来自artists的文档:

         [_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 首曲目 我认为它会很慢......

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

【问题讨论】:

    标签: php mongodb schema schema-design


    【解决方案1】:

    嗯,这是一个非常相关的问题,使用非关系数据库来解决这样的问题需要一些努力。总的来说,我认为您的架构设计很好。

    您所描述的称为“N+1 问题”,因为您必须对 N 个对象进行 N+1 次查询(在您的情况下,它更复杂,但我想您明白了)。

    一些补救措施:

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

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

      如果艺术家的数组变得庞大,这将不起作用,但几百个,也许一千个应该可以正常工作。确保 artists 已编入索引。

    • 您可以对一些经常需要的信息进行非规范化处理。例如,您可能希望经常显示曲目列表,因此将艺术家的姓名复制到每个曲目是有意义的。非规范化主要取决于您从最终用户的角度尝试实现的目标。您可能不想完整存储每个艺术家的姓名,而只存储前 50 个字符,因为 UI 无论如何都不会在概览中显示更多内容。

      事实上,您已经对一些数据进行了非规范化处理,例如专辑中的艺术家 ID(这是多余的,因为您也可以通过曲目获取它们)。这使查询更容易,但它会更繁重。更新很难看,因为您必须确保它们通过系统传播。

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

    【讨论】:

    • 感谢@mnemosyn 我将专辑链接回艺术家的原因是因为我需要他们在那里,我并不总是想要获得曲目,有时我只想要专辑,以及将艺术家的名字直接放在曲目文件上是个好主意,我试过了,效果很好,但我想看看是否有人想出了更好的主意....
    • 谢谢,我想我会去规范化,因为。艺术家、专辑和曲目的名称和详细信息只会因为我的一个管理员拼写错误而改变,所以我不会一直写....
    猜你喜欢
    • 2012-08-25
    • 2011-05-25
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 2018-07-04
    • 2011-11-20
    • 2015-04-21
    相关资源
    最近更新 更多