Лучший способ сделать один-ко-многим «JOIN» в CouchDB

Я ищу эквивалент CouchDB для «SQL-соединений».

В моем примере есть документы CouchDB, которые являются элементами списка:

{ "type" : "el", "id" : "1", "content" : "first" } { "type" : "el", "id" : "2", "content" : "second" } { "type" : "el", "id" : "3", "content" : "third" } 

Список содержит один документ:

 { "type" : "list", "elements" : ["2","1"] , "id" : "abc123" } 

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

Результатом может быть:

 { "content" : ["second", "first"] } 

В этом случае порядок элементов уже как и должен быть. Другой возможный результат:

 { "content" : [{"content" : "first", "order" : 2},{"content" : "second", "order" : 1}] } 

Я начал писать функцию карты:

 map = function (doc) { if (doc.type === 'el') { emit(doc.id, {"content" : doc.content}); //emit the id and the content exit; } if (doc.type === 'list') { for ( var i=0, l=doc.elements.length; i<l; ++i ){ emit(doc.elements[i], { "order" : i }); //emit the id and the order } } } 

Это насколько я могу получить. Можете ли вы исправить мои ошибки и написать функцию сокращения? Помните, что третий документ не должен быть частью результата.

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


EDIT: Не пропустите комментарий Джейсона Смита к его ответу, где он описывает, как сделать это короче.

Спасибо! Это отличный пример, чтобы показать новые возможности CouchDB 0.11 !

Вы должны использовать функцию связанных с выборкой данных для ссылки на документы в представлении. При желании для более удобного JSON используйте функцию _list для очистки результатов. Для получения дополнительной информации см. Запись Couchio на «JOIN» .

Вот план:

  1. Во-первых, у вас есть уникальность в ваших документах. Если два из них имеют id = 2, это проблема. Вместо этого нужно использовать поле _id если id . CouchDB гарантирует уникальность, но также для остальной части этого плана требуется _id для получения документов по идентификатору.

     { "type" : "el", "_id" : "1", "content" : "first" } { "type" : "el", "_id" : "2", "content" : "second" } { "type" : "el", "_id" : "3", "content" : "third" } 

    Если изменить документы для использования _id абсолютно невозможно, вы можете создать простой вид для emit(doc.id, doc) а затем повторно вставить его во временную базу данных. Это преобразует id в _id но добавляет некоторую сложность.

  2. Представление испускает {"_id": content_id} данные с ключом [list_id, sort_number] , чтобы «скомбинировать» списки с их содержимым.

     function(doc) { if(doc.type == 'list') { for (var i in doc.elements) { // Link to the el document's id. var id = doc.elements[i]; emit([doc.id, i], {'_id': id}); } } } 

    Теперь есть простой список el документов, в правильном порядке. Вы можете использовать startkey и endkey если хотите видеть только определенный список.

     curl localhost:5984/x/_design/myapp/_view/els {"total_rows":2,"offset":0,"rows":[ {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","0"],"value":{"_id":"2"}}, {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","1"],"value":{"_id":"1"}} ]} 
  3. Чтобы получить el контент, запросите include_docs=true . Через магию _id будут загружены документы el .

     curl localhost:5984/x/_design/myapp/_view/els?include_docs=true {"total_rows":2,"offset":0,"rows":[ {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","0"],"value":{"_id":"2"},"doc":{"_id":"2","_rev":"1-4530dc6946d78f1e97f56568de5a85d9","type":"el","content":"second"}}, {"id":"036f3614aeee05344cdfb66fa1002db6","key":["abc123","1"],"value":{"_id":"1"},"doc":{"_id":"1","_rev":"1-852badd683f22ad4705ed9fcdea5b814","type":"el","content":"first"}} ]} 

    Обратите внимание, что это уже вся необходимая информация. Если ваш клиент является гибким, вы можете анализировать информацию из этого JSON. Следующий необязательный шаг просто переформатирует его, чтобы он соответствовал тому, что вам нужно.

  4. Используйте функцию _list , которая просто переформатирует вывод представления. Люди используют их для вывода XML или HTML, но мы сделаем JSON более удобным.

     function(head, req) { var headers = {'Content-Type': 'application/json'}; var result; if(req.query.include_docs != 'true') { start({'code': 400, headers: headers}); result = {'error': 'I require include_docs=true'}; } else { start({'headers': headers}); result = {'content': []}; while(row = getRow()) { result.content.push(row.doc.content); } } send(JSON.stringify(result)); } 

    Результаты совпадают. Конечно, в производстве вам понадобится startkey и endkey чтобы указать endkey вам список.

     curl -g 'localhost:5984/x/_design/myapp/_list/pretty/els?include_docs=true&startkey=["abc123",""]&endkey=["abc123",{}]' {"content":["second","first"]} 
  • размер блока данных в HDFS, почему 64 МБ?
  • Установка количества задач карты и сокращение задач
  • Как получить имя входного файла в Mapper в программе Hadoop?
  • Какова цель фаз перетасовки и сортировки в редукторе в Программе сокращения карты?
  • Нет такого исключения метода Hadoop
  • Лучше ли использовать карту или пакет mapreduce для создания задания Hadoop?
  • Oozie: Launch Map-Reduce от Oozie action?
  • Как Hadoop выполняет входные расщепления?
  • Где hasoop mapreduce framework отправляет мои инструкции System.out.print ()? (стандартный вывод)
  • Узел имени находится в безопасном режиме. Не в состоянии уйти
  • Является ли структура агрегации Mongodb быстрее, чем карта / сокращение?
  • Interesting Posts
    Давайте будем гением компьютера.