2015-12-17 7 views
2

Я использую pouchDb в электронном приложении. Данные были сохранены в базе данных postgres, прежде чем перейти к pouchDb. В некоторых случаях было не сложно понять, как структурировать данные в документе.Каков наиболее эффективный способ чтения отношений из базы данных pouchdb

Моя основная забота касается отношений. Например:

У меня есть тип данных Проекты и проекты имеют много событий. Прямо сейчас у меня есть поле под названием project_id для каждого события. Поэтому, когда я хочу, чтобы получить события для проекта с ID «Проект/1» Я сделаю

_db.allDocs({ 
    include_docs: true, 
    startkey: 'event', 
    endkey: 'event\uffff' 
}).then(function(response){ 
    filtered = _.filter(response['rows'], function(row){ 
     return row['doc']['project_id'] == 'project/1' 
    }); 
    result = filtered.map(function(row){ 
     return row['doc'] 
    }) 
}); 

Я читал, что allDocs является наиболее производительным API, но, имея ли вид более удобным на Это дело?

С другой стороны, когда я показываю список со всеми проектами, каждый проект должен показывать количество событий, которые он имеет. По этому сценарию, похоже, мне придется снова запустить allDocs, с include_docs: false, чтобы подсчитать количество событий, которые имеет проект.

Имеет ли вид зрения улучшает эту ситуацию?

С другой стороны, я думаю о наличии массива со всеми идентификаторами событий в документе Project, поэтому я могу легко подсчитать, сколько событий оно имеет. В этом случае следует использовать allDocs? Есть ли способ передать массив Ids для allDocs? Или было бы лучше использовать цикл над этим массивом и вызвать get (id) для каждого id?

Является ли это другим способом более совершенным, чем первый?

Спасибо!

ответ

6

Хороший вопрос! Существует много способов обработки отношений в PouchDB. И, как и многие базы данных NoSQL, каждый из них даст вам компромисс производительности и удобства.

Система, которую вы описываете, не очень эффективна. В основном вы извлекаете каждое событие в базе данных (O(n)), а затем фильтруете в памяти. Если у вас много событий, то n будет большим, а это значит, что он будет очень медленным.

У вас здесь есть несколько вариантов. Все они лучше, чем ваша текущая система:

  1. . То есть в вашей функции map, вы должны emit() проект _id s для каждого события. Это создает вторичный индекс для того, что вы поставили как key в функции emit().
  2. relational-pouch, который является плагином, который работает с использованием префикса _id и работает allDocs() с startkey и endkey для каждого из них. Таким образом, для получения проекта потребуется allDocs(), затем allDocs() для получения событий для этого проекта.
  3. Полностью отдельные базы данных, например. new PouchDB('projects') и new PouchDB('events')

(Грубо они перечислены ниже, чем наименее эффективны.)

# 1 более совершенен, чем система, которую вы описываете, хотя она все еще не очень быстро, потому что она требует создания вторичного индекса, а затем после этого будет по существу делать allDocs() по базе данных вторичных индексов, а также по исходная база данных (для получения связанных документов). Так что в основном вы бежите allDocs() три раза под капотом –, один из которых находится на том, что вы выбрали как key, который кажется вам не нужен, поэтому он просто будет потрачен впустую.

# 2 намного лучше, потому что под капотом он запускает два быстрых запроса allDocs() - один для извлечения проекта, а другой - для получения событий. Это также не требует создания вторичного индекса; он может использовать бесплатный _id индекс.

# 3 также требуется два вызова allDocs(). Так почему это быстрее? Ну, интересно, это из-за того, как IndexedDB заказывает операции чтения/записи под капотом. Предположим, вы пишете как 'projects', так и 'events'. Что IndexedDB будет делать, так это сериализовать эти две записи, потому что он не может быть уверен, что они не будут изменять одни и те же документы. (Однако, когда дело доходит до чтения, два запроса могут выполняться одновременно в любом случае – в Chrome, по крайней мере. Я полагаю, что Firefox фактически сериализует чтение.) Так что в основном, если у вас есть два полностью отдельных PouchDB, представляющих два полностью отдельных IndexedDBs , то оба чтения и записи могут выполняться одновременно.

Конечно, в случае отношений между родителями и дочерними элементами вы не можете заранее знать дочерние идентификаторы, поэтому вам нужно все равно получить родительский элемент, а затем извлечь детей. Таким образом, в этом случае нет разницы в производительности между # 2 и # 3.

В вашем случае, я бы сказал, что лучший выбор, вероятно, № 2. Это хороший компромисс между перфомансом и удобством, тем более что плагин relational-pouch уже выполняет эту работу за вас.