представляя отношения многие ко многим в couchDB - PullRequest
3 голосов
/ 01 декабря 2009

Допустим, я пишу приложение для анализа журналов. Основным объектом домена будет LogEntry. К тому же. пользователи приложения определяют LogTopic, который описывает, какие записи журнала им интересны. Когда приложение получает записи журнала, оно добавляет их в couchDB, а также проверяет их по всем LogTopics в системе, чтобы увидеть, соответствуют ли они критериям в теме , Если это так, то система должна записать, что запись соответствует теме. Таким образом, между LogEntries и LogTopics существует отношение «многие ко многим».

Если бы я хранил это в РСУБД, я бы сделал что-то вроде:

CREATE TABLE Entry (
 id int,
 ...
)

CREATE TABLE Topic (
 id int,
 ...
)

CREATE TABLE TopicEntryMap (
 entry_id int,
 topic_id int
)

Использование CouchDB Сначала я попробовал использовать только два типа документов. У меня был бы тип LogEntry, похожий на этот:

{
  'type': 'LogEntry',
  'severity': 'DEBUG',
  ...
}

и у меня будет тип LogTopic, похожий на этот:

{
  'type': 'LogTopic',
  'matching_entries': ['log_entry_1','log_entry_12','log_entry_34',....],
  ...
}

Вы можете видеть, что я представляю взаимосвязь, используя поле matching_entries в каждом документе LogTopic для хранения списка идентификаторов документов LogEntry. Это работает хорошо до некоторой степени, но у меня есть проблемы, когда несколько клиентов пытаются добавить соответствующую запись в тему. Обе пытаются выполнить оптимистичные обновления, а одна не удается. Решение, которое я использую сейчас, заключается в том, чтобы по существу воспроизвести подход RDBMS и добавить третий тип документа, например:

{
  'type':'LogTopicToLogEntryMap',
  'topic_id':'topic_12',
  'entry_id':'entry_15'
}

Это работает и устраняет параллельные проблемы с обновлением, но у меня есть две оговорки:

  1. Я волнуюсь, что я просто использую это подход, потому что это то, что я бы сделал в реляционная БД. Интересно, есть ли более couchDB-подобный (расслабляющий?) решение.
  2. Мои взгляды больше не могут получить все записи для конкретная тема в один звонок. мой предыдущее решение позволило это (если я использовал параметр include_docs).

У кого-нибудь есть лучшее решение для меня? Поможет ли мне опубликовать просмотры, которые я использую?

Ответы [ 3 ]

11 голосов
/ 01 декабря 2009

Я отправил этот вопрос в список рассылки пользователей couchdb , а Натан Стотт указал мне на очень полезное сообщение в блоге от Christopher Lenz

4 голосов
/ 01 декабря 2009

Ваш подход в порядке. Использование CouchDB не означает, что вы просто откажетесь от реляционного моделирования. Вам нужно будет выполнить два запроса, но это потому, что это «соединение». Запросы SQL с объединениями также являются медленными, но синтаксис SQL позволяет выразить запрос в одном выражении.

За несколько месяцев работы с CouchDB я обнаружил следующее:

  1. Нет схемы, поэтому разработка моделей приложений быстрая и гибкая
  2. CRUD есть, поэтому разработка вашего приложения происходит быстро и гибко
  3. Прощай, SQL-инъекция
  4. То, что было бы соединением SQL, требует немного больше работы в CouchDB

В зависимости от ваших потребностей я обнаружил, что couchdb-lucene также полезен для построения более сложных запросов.

0 голосов
/ 13 августа 2010

Я бы попытался установить отношение, чтобы LogEntrys знал, к каким LogTopics они принадлежат. Таким образом, вставка LogEntry не вызовет конфликтов, так как LogTopics не нужно будет изменять.

Затем простая функция карты будет генерировать LogEntry один раз для каждой LogTopic, к которой она принадлежит, по сути, создавая ваш TopicEntryMap на лету:

"map": function (doc) {
    doc.topics.map(function (topic) {
        emit(topic, doc);
    });
}

Таким образом, запрос представления с аргументом ?key=<topic> даст вам все записи, относящиеся к теме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...