Отношение "многие ко многим" с базой данных NoSQL - программирование
Подтвердить что ты не робот

Отношение "многие ко многим" с базой данных NoSQL

Я хочу реализовать структуру таксономии (гео термины) для моего приложения node.js с базой данных NoSQL. У меня была аналогичная структура таксономии с MySQL, но мне пора двигаться вперед и узнать что-то новое, поэтому я решил попробовать другой подход и использовать NoSQL (ориентированный на документ) для своего тестового приложения. Структура таксономии проста - существует пять разных уровней: страна (т.е. Великобритания) → регион (Англия) → уезд (Мерсисайд) → город/населенный пункт (Ливерпуль) → часть города (Токстет).

Очевидным выбором является использование древовидной структуры, но дьявол находится в деталях - исторически некоторые города и города принадлежали другим округам. Идея заключалась в том, чтобы пометить лиц, родившихся в определенных городах или городах с этими условиями, и отфильтровать их позже гео-тегами, поэтому я должен уважать тот факт, что Ливерпуль или Манчестер (в том числе) были частью Ланкашира в то время, когда родились некоторые люди, В противном случае результат, полученный любым пользователем с моим геофильтром, будет неправильным.

Пример: Джон Доу родился в Блэкберне (Ланкашир) еще в 1957 году. Пол Браун родился в 1960 году в Ливерпуле (Ланкашир, теперь Мерсисайд). Джорджия Доу (урожденная Джонс) родилась в Виррале (Чешир, теперь Мерсисайд) 5 лет спустя. Их сын Ринго родился в Ливерпуле (Мерсисайд к тому времени) в 1982 году.

Джон - Ланкастриан по происхождению, Пол - Ланкастриан и Мерсисидер, Грузия из Чешира и Мерсисайд в то же время, Ринго из Мерсисайд. Поэтому их следует классифицировать, когда я ищу по округу. Но с простой структурой "один ко многим", которая следует за современной структурой страны, они никогда не будут отфильтрованы, как и должно быть.

Как реализовать коллекцию с учетом сложности ее структуры с помощью NoSQL (в первую очередь, для документирования) решений? Я просмотрел его и сделал несколько исследований по стеке *, но до сих пор не знал, что делать дальше. На мой взгляд, есть несколько возможных путей решения этой проблемы:

  • Используйте SQL-подобную структуру данных:

    {
        {'name': 'United Kingdom', 'unique_id': 1},
        {'name': 'England', 'unique_id': 2, 'parents': [1]},
        {'name': 'Merseyside', 'unique_id': 3, 'parents': [2]},
        {'name': 'Lancashire', 'unique_id': 4, 'parents': [2]},
        {'name': 'Liverpool', 'unique_id': 5, 'parents': [3, 4]},
    }
    
  • Используйте древовидную структуру с некоторыми ссылками:

    {    
        {'name': 'United Kingdom', 'unique_id': 1
            {'name': 'England', 'unique_id': 2]
                {'name': 'Merseyside', 'unique_id': 3]
                    {'name': 'Liverpool', 'unique_id': 5, 'alternate_parents': [4]},
                },
                {'name': 'Lancashire', 'unique_id': 4},
            },
        },
    }
    
  • Используйте древовидную структуру без ссылок (один-ко-многим) и добавьте тег "альтернативный родительский" в документ вручную:

    {    
        {'name': 'United Kingdom', 'unique_id': 1
            {'name': 'England', 'unique_id': 2]
                {'name': 'Merseyside', 'unique_id': 3]
                    {'name': 'Liverpool', 'unique_id': 5},
                },
                {'name': 'Lancashire', 'unique_id': 4},
            },
        },
    }
    
  • Придерживайтесь SQL.

  • Попробуйте реализовать таксономию без базы данных.

Дайте мне совет по этому поводу, пожалуйста. Я новичок с любым NoSQL (в настоящее время я не создавал таких баз данных), поэтому для меня существует реальная проблема дизайна.

И я новичок в стеке *, поэтому не стесняйтесь исправить меня, если я сделал что-то не так с этим сообщением:) Спасибо!

ИЗМЕНИТЬ Я выбрал @Jonathan ответ как решение. Я думаю, что это лучше подходит для моих нужд (в моей базе данных будут храниться другие документы и помечать их этими терминами), особенно с помощью функции mapReduce, предложенной @Valentyn.

Но если для вашего приложения нет необходимых коллекций документов, то возможно наилучшее возможное решение для базы данных графов (на основе отношений, а не документов), предложенной @Philipp.

4b9b3361

Ответ 1

Во-первых, выбор между NoSQL и базой данных SQL затруднен, если вы не знакомы с основными принципами. Если это единственные данные, которые вы храните, перейдите к реляционной (SQL). Если есть больше данных (которые я предполагаю), и для этого требуется больше переплетенной схемы, придерживайтесь рук NoSQL.

Я бы использовал реляционный маршрут для этого, чтобы он не становился слишком сложным... запустите несколько коллекций; один для стран, регионов и т.д. Не обескураживайте выполнение реляционных (SQL) типов в базе данных NoSQL; большую часть времени они являются лучшим решением.

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

Например:

{
    {'name': 'United Kingdom'},
    {'name': 'United States'}
}

{
    {'name': 'England', 'parent': 'United Kingdom'},
    {'name': 'California', 'parent': 'United States'}
}

Таким образом, ваш набор данных не будет настолько вложенным, что возвращаемые данные будут неуправляемыми. Затем вы можете легко с легкостью захватить страны и соответствующие регионы... и т.д.

Удачи!

EDIT: ответы на вопросы OP:

(Во-первых, я бы рекомендовал MongoDB - это отличное решение.)

  • Потому что, когда вы начинаете работать с MongoDB, вы поймете, что он хранит данные бок о бок на жестком диске. Если вы отредактируете такую ​​огромную запись, ее скорее всего вытащите на заднюю часть диска, сделав жесткий диск похожим на швейцарский сыр. Как только вы доберетесь до этого момента, вам придется ремонтировать его еще раз. Кроме того, таким образом, данные легче разделяются в вашем приложении, таким образом, если вам нужно что-то сделать с данными, вам не придется применять его ко всему объекту. Я предполагаю, что у вас будет большой набор данных, поскольку в мире существует много разных мест.

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

  • Вместо массива я бы использовал вложенный документ для хранения нескольких родителей. Таким образом, его можно легко запросить и проиндексировать. Я бы использовал следующий метод:

    {
        {
            'name': 'England,
            'parent': {
                1: 1,
                568: 1
            }
         }
     }
    

Таким образом, вы можете использовать свою идею индексов и найти, где db.region.$.568= 1

Ответ 2

Из-за сделанного вами комментария, я предполагаю, что вы имеете в виду "MongoDB", когда вы говорите "NoSQL". Существует много других технологий баз данных, которые обычно называются NoSQL, которые совершенно разные, но это похоже на то, что вы имеете в виду.

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

  • и 3. Один документ, который является огромным деревом, также не является хорошей идеей, поскольку MongoDB имеет ограничение на 16 МБ на документ. Когда вы создаете огромные монолитные документы, вы можете попасть в этот предел.

Я думаю, что MongoDB может быть не лучшим решением для вашего случая использования. Вы рассматривали использование графика базы данных? MongoDB оптимизирован для самостоятельных документов, которые стоят самостоятельно. Но фокус баз данных графов основан на наборах данных, где у вас много объектов, которые определяются их отношениями с другими объектами. Это очень похоже на ваш случай использования.