MongoDB Схема Дизайн.не могу получить то, что я хочу - PullRequest
3 голосов
/ 14 декабря 2011

Мне кажется, у меня проблема с дизайном схемы для моего музыкального приложения.

У меня есть 3 коллекции: Artists, Tracks и Albums.и 3 класса: artists, albums и tracks

документ от 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 треков, я думаю, что это будет очень медленно ...

, поэтому мой вопрос: Это хороший дизайн схемы ?

1 Ответ

3 голосов
/ 14 декабря 2011

Ну, это очень реляционная проблема, и использование нереляционной базы данных для такой проблемы требует определенных усилий. В целом, я думаю, что ваш дизайн схемы хорош.

То, что вы описываете, называется «проблемой N + 1», потому что вам придется делать N + 1 запросов для N объектов (в вашем случае это сложнее, но я думаю, вы поняли).

Некоторые средства правовой защиты:

  • Вы можете использовать оператор $in, чтобы найти, например, все треки определенного исполнителя:

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

    Это не сработает, если множество артистов вырастет огромным, но несколько сотен, может быть, тысяча должно работать нормально. Убедитесь, что artists проиндексирован.

  • Вы можете денормализовать часть информации, которая нужна очень часто. Например, вы можете захотеть показывать список дорожек очень часто, поэтому имеет смысл копировать имена исполнителей на каждую дорожку. Денормализация в основном зависит от того, чего вы пытаетесь достичь с точки зрения конечного пользователя. Возможно, вы не захотите хранить имя каждого исполнителя полностью, а только первые 50 символов, потому что пользовательский интерфейс в любом случае больше не отображается в обзоре.

    Фактически, вы уже денормализуете некоторые данные, такие как идентификаторы артиста в альбоме (которые являются избыточными, потому что вы также можете получать их через треки). Это делает запросы проще, но это будет более трудоемким для записи. Обновления ужасны, потому что вам нужно убедиться, что они распространяются по системе.

  • В некоторых случаях может иметь смысл «присоединиться» к клиенту (!), А не к серверу. Это не совсем подходит для вашей проблемы, но стоит отметить: предположим, у вас есть список друзей. Теперь сервер должен будет искать имя каждого друга, когда он их отображает. Вместо этого он может предоставить вам идентификаторы / друзья из таблицы поиска, а сервер обслуживает только идентификаторы. Некоторые JavaScript могут заменить идентификаторы реальными именами из кэша клиента.

...