Просмотры Couchdb и многие (тысячи) типы документов

#optimization #view #couchdb #organization

#оптимизация #Вид #couchdb #организация

Вопрос:

Я изучаю CouchDB и представляю наихудший сценарий:

для каждого типа документа мне нужно 3 вида, и это приложение может генерировать 10 тысяч типов документов.

Под «типом документа» я подразумеваю структуру документа.

После вставки нового документа couchdb выполняет 3 * 10K вызовов функций просмотра, ищущих нужный тип документа.

Это правда? Есть ли более разумное решение, чем создание базы данных для каждого типа документа?

Пример документа (предположим, что ни один документ не имеет одинаковой структуры, в этом примере данные находятся под разными ключами):

 [
     {
       "_id":"1251888780.0",
       "_rev":"1-582726400f3c9437259adef7888cbac0"
       "type":'sensorX',
       "value":{"ValueA":"123"}
     },
     {
       "_id":"1251888780.0",
       "_rev":"1-37259adef7888cbac06400f3c9458272"
       "type":'sensorY',
       "value":{"valueB":"456"}
     },
     {
       "_id":"1251888780.0",
       "_rev":"1-6400f3c945827237259adef7888cbac0"
       "type":'sensorZ',
       "value":{"valueC":"789"}
     },
   ]
  

Пример просмотров (в этом примере только один для каждого типа документа)

   "views":
  {
    "sensorX": {
      "map": "function(doc) { if (doc.type == 'sensorX')  emit(null, doc.valueA) }"
    },
    "sensorY": {
      "map": "function(doc) { if (doc.type == 'sensorY')  emit(null, doc.valueB) }"
    },
    "sensorZ": {
      "map": "function(doc) { if (doc.type == 'sensorZ')  emit(null, doc.valueC) }"
    },
  }
  

Комментарии:

1. Можете ли вы привести пример того, что вы подразумеваете под типом документа?

2. Я думаю, что ваш «Пример документа» содержит не документы, а результат просмотра. Можете ли вы опубликовать несколько примеров документов? Вы можете найти их через Futon .

Ответ №1:

Результаты map() функции в CouchDB кэшируются при первом запросе просмотра для каждого нового документа. Позвольте мне объяснить с помощью краткой иллюстрации.

  • Вы вставляете 100 документов в CouchDB

  • Вы запрашиваете просмотр. Теперь для 100 документов выполняется map() функция, а результаты кэшируются.

  • Вы снова запрашиваете просмотр. Данные считываются из индексированных данных просмотра, никаких документов не требуется повторно отображать.

  • Вы вставляете еще 50 документов

  • Вы запрашиваете просмотр. 50 новых документов сопоставлены и объединены в индекс со старыми 100 документами.

  • Вы снова запрашиваете просмотр. Данные считываются из индексированных данных просмотра, никаких документов не требуется повторно отображать.

Я надеюсь, что это имеет смысл. Если вы обеспокоены большой нагрузкой, создаваемой, когда пользователь запрашивает просмотр и было добавлено много новых документов, вы могли бы подумать о том, чтобы ваш процесс импорта вызывал просмотр (для повторного сопоставления новых документов) и включал пользовательский запрос на просмотр stale=ok .

Книга CouchDB — действительно хороший ресурс для получения информации о CouchDB.

Комментарии:

1. Да, теперь, когда результаты просмотра в кэше CouchDB, я сомневаюсь, что в _design documents есть тысячи функций просмотра.

2. Я думаю, вам нужно переосмыслить, как вы собираетесь использовать CouchDB. Наличие функции просмотра тысяч — почти наверняка плохой план. Я бы посоветовал вам изменить вашу функцию просмотра таким образом, чтобы она выдавала ключ [doc.type, doc.value]. Вам нужно убедиться, что функция просмотра включает логику для работы со значением для выдачи.

3. Проблема в том, что я не знаю логики для работы с каждым типом документа, она определяется пользователем, и в худшем случае у каждого пользователя своя логика. Вот почему моей первой идеей было использовать представления типа «адаптеры», преобразующие документы с неизвестной структурой в документы с хорошо известной структурой. Что вы думаете об использовании одной базы данных для каждого типа данных? Может ли CouchDB обрабатывать тысячи баз данных?

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

5. Я подозреваю, что вы начали бы сталкиваться с проблемами fs, если бы у вас были тысячи баз данных. Я бы рекомендовал рассмотреть другие способы решения проблемы, возможно, нормализовать данные перед их отправкой в CouchDB или, возможно, полностью переосмыслить модель данных.

Ответ №2:

У Джеймса есть отличный ответ.

Похоже, вы задаете вопрос «каковы значения документов типа X?»

Я думаю, вы можете сделать это с помощью одного представления:

 function(doc) {
    // _view/sensor_value
    var val_names = { "sensorX": "valueA"
                    , "sensorY": "valueB"
                    , "sensorZ": "valueC"
                    };

    var value_name = val_names[doc.type];
    if(value_name) {
        // e.g. "sensorX" -> "123"
        // or "sensorZ" -> "789"
        emit(doc.type, doc.value[value_name]);
    }
}
  

Теперь, чтобы получить все значения для sensorY , вы запрашиваете /db/_design/app/_view/sensor_value с параметром ?key="sensorX" . CouchDB покажет все значения для sensorX, которые поступают из value.valueA поля документа. (Для сенсорных, это происходит из value.valueB и т.д.)

Проверка на будущее

Если в будущем у вас могут появиться новые типы документов, возможно, лучше использовать что-то более общее:

 function(doc) {
     if(doc.type amp;amp; doc.value) {
         emit(doc.type, doc.value);
     }
 }
  

Это очень просто, и любой документ будет работать, если в нем есть поле type и value . Далее, чтобы получить valueA , valueB и т.д. Из представления, просто сделайте это на стороне клиента.

Если использование клиента невозможно, используйте _list функцию.

 function(head, req) {
    // _list/sensor_val
    //
    start({'headers':{'Content-Type':'application/json'}});

    // Updating this will *not* cause the map/reduce view to re-build.
    var val_names = { "sensorX": "valueA"
                    , "sensorY": "valueB"
                    , "sensorZ": "valueC"
                    };


    var row;
    var doc_type, val_name, doc_val;
    while(row = getRow()) {
        doc_type = row.key;
        val_name = val_names[doc_type];
        doc_val = row.value[val_name];
        send("Doc "   row.id   " is type "   doc_type   " and value "   doc_val);
    }
}
  

Очевидно, используйте send() для отправки клиенту любого формата, который вы предпочитаете (например, JSON).

Комментарии:

1. недостатком этого решения является необходимость добавления нового типа документа: представление должно быть перестроено с разбором всех документов.

2. Обновлен ответ, чтобы учесть неизвестные будущие типы документов