CouchDB: связывание документа, ссылающегося на массив различных типов документов

Я новичок, когда дело доходит до CouchDB. Я пришел из мира .NET SQL Server.

в скольжении через CouchDB окончательное руководство я был как "ВУТ ВУТ это потрясающе". Теперь я тестирую некоторые вещи, которые я узнал в надежде реализовать его в реальном мире.

Я только что зарегистрировался на учетную запись Cloudant пару недель назад и начал использовать ее для тестирования/обучения.

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

возьмите, например, этот SQL-запрос. Предполагая, что в каждой из таблиц есть только одна запись, мы должны получить одну запись со всеми детали для обуви с заданным sku. Но если бы у нас было несколько размеров обуви, нам пришлось бы написать еще немного кода.

select ci.sku
        ,sc.color
        ,ss.size
        ,si.url
from CatalogItem ci
    join ShoeImages si
        on ci.sku = si.sku
        and ci.sku = '656F-PINSEC12'
    join ShoeSizes ss
        on ci.sku = ss.sku
    join ShoeColors sc
        on ci.sku = sc.sku

Я хотел бы CouchDB вернуть следующий JSON SKU на https://username.cloudant.com/test/_design/catalogue/_view/item-details?include_docs=true&key=%22656F-PINSEC12%22

{
   "_id": "689fe6982f4d604541db67ee4050a535",
   "_rev": "5-64b5ddd751c51aadfcef1962c2c99c16",
   "type": "catalogue-item",
   "sku": "656F-PINSEC12",
   "upc": "8549875231",
   "shoe-colors": 
   [
        {
            "color": "black/houndstooth"
            "shoe-sizes": 
            [
                {
                    "size": 5,
                    "IsSizeAvailable": true
                },
                {
                    "size": 6,
                    "IsSizeAvailable": true
                },
                {
                    "size": 7,
                    "IsSizeAvailable": true
                },
                {
                    "size": 8,
                    "IsSizeAvailable": true
                },
                {
                    "size": 9,
                    "IsSizeAvailable": true
                },
                {
                    "size": 10,
                    "IsSizeAvailable": true
                },
                {
                    "size": 11,
                    "IsSizeAvailable": true
                },
                {
                    "size": 12,
                    "IsSizeAvailable": true
                },
                {
                    "size": 13,
                    "IsSizeAvailable": true
                },
                {
                    "size": 14,
                    "IsSizeAvailable": true
                }
            ],
            "shoe-images": 
            [
                {
                    "full-images": 
                    [
                        "http://www.someurl.com/full/656F-PINSEC12.jpg"
                    ],
                    "thumbnail-images": 
                    [
                        "http://www.someurl.com/thumb/656F-PINSEC12.jpg"
                    ]
                }
            ]
        }
    ]
}

учитывая следующие документы и карту / уменьшить:

//--catalog item
{
   "_id": "689fe6982f4d604541db67ee4050a535",
   "_rev": "5-64b5ddd751c51aadfcef1962c2c99c16",
   "type": "catalogue-item",
   "sku": "656F-PINSEC12",
   "upc": "8549875231",
   "shoe-colors": [
       {
           "_id": "bbbb92c3d61ed9f4f0e8111fb20fcf43",
           "shoe-images": [
               {
                   "_id": "7b547bae4ac911c6f05b97eba6cb355a"
               }
           ],
           "shoe-sizes": [
               {
                   "_id": "12b6289d558d7ceb5bef725091666ce5"
               }
           ]
       }
   ]
}

//--shoe images
{
   "_id": "7b547bae4ac911c6f05b97eba6cb355a",
   "_rev": "4-4fde0cac1b4b8afc618bbba5b6669193",
   "type": "shoe-images",
   "sku": "656F-PINSEC12",
   "color": "Black/Houndstoot",
   "full-images": [
       "http://www.someurl.com/full/656F-PINSEC12.jpg"
   ],
   "thumbnail-images": [
       "http://www.someurl.com/thumb/656F-PINSEC12.jpg"
   ]
}

//--shoe color
{
   "_id": "bbbb92c3d61ed9f4f0e8111fb20fcf43",
   "_rev": "2-e5d07c00a0261c231dd2be9b26a6c0dc",
   "type": "shoe-color",
   "sku": "656F-PINSEC12",
   "color": "black/houndstooth"
}

//--shoe sizes
{
   "_id": "12b6289d558d7ceb5bef725091666ce5",
   "_rev": "2-192df709f9de1ef27e9e5f4404863bcc",
   "type": "shoe-sizes",
   "sku": "656F-PINSEC12",
   "shoe-color": "black/houndstooth",
   "shoe-sizes": [
       {
           "size": 5,
           "IsSizeAvailable": true
       },
       {
           "size": 6,
           "IsSizeAvailable": true
       },
       {
           "size": 7,
           "IsSizeAvailable": true
       },
       {
           "size": 8,
           "IsSizeAvailable": true
       },
       {
           "size": 9,
           "IsSizeAvailable": true
       },
       {
           "size": 10,
           "IsSizeAvailable": true
       },
       {
           "size": 11,
           "IsSizeAvailable": true
       },
       {
           "size": 12,
           "IsSizeAvailable": true
       },
       {
           "size": 13,
           "IsSizeAvailable": true
       },
       {
           "size": 14,
           "IsSizeAvailable": true
       }
   ]
}

//--map/reduce
{
   "_id": "_design/catalog",
   "_rev": "4-de5baf04b485768de12d78e5a0e5aa5e",
   "views": {
       "item": {
           "map": "function(doc) 
                {
                  if (doc.type === 'catalog-item') 
                  {
                    emit([doc.sku, doc], null);
                    if (doc.shoe-colors) 
                    {
                      for (var sc in doc.shoe-colors) 
                      {
                        emit([doc.sku, Number(sc)+1], {_id: doc.shoe-colors[sc]._id});
                        for (var si in doc.shoe-colors[sc].shoe-images) 
                        {
                            emit([doc.sku, Number(si)+1], {_id: doc.shoe-colors[sc].shoe-images[si]._id});
                        }
                        for (var sz in doc.shoe-colors[sc].shoe-sizes) 
                        {
                            emit([doc.sku, Number(sz)+1], {_id: doc.shoe-colors[sc].shoe-sizes[sz]._id});
                        }
                      }
                    }
                  }
                }"
       }
   }
}

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

{"total_rows":0,"offset":0,"rows":[

]}

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

Надеюсь, мой вопрос имеет смысл Oo_ _ oO

1 ответов


трюк с этим-уйти от мышления в терминах соединений. Связанные документы дают вам метод индексирования одного типа документа на основе свойств другого. Это работает с использованием комбинации двух функций:

  1. CouchDB позволяет указать include_docs=true при запросе представления для возврата индексированных документов вместе с результатами представления.
  2. вы можете сказать CouchDB, чтобы вернуть любой документ, указав свойство _id в результате просмотра. Заметить что вы все еще можете вернуть только один документ за результат.

в качестве примера, скажем, у вас были документы

{
     "_id": "111",
     "type", "shoe",
     "sku": "656F-PINSEC12",
     "shoe-color": "black/houndstooth",
     "imageId": "222"
}

и

{
     "_id": "222",
     "type": "image",
     "full-images": ["http://www.someurl.com/full/656F-PINSEC12.jpg"]
     "thumbnail-images": ["http://www.someurl.com/thumb/656F-PINSEC12.jpg"]
}

тогда вы можете индексировать изображения SKU с помощью функции карты:

function(doc) {
     if(doc.type === "shoe") {
         emit(doc.sku, {_id: doc.imageId });
     }
}

также важно понимать, что функция карты работает только с сохраненным исходным документом.

Я думаю, что в вашем примере документы "элемент каталога" и "цвет обуви" являются избыточными. Можно определить карту функция индексирования документов" изображение обуви "и" размер обуви " SKU, например

function(doc) {
    if(doc.SKU) {
        emit(doc.SKU, null);
    }
}

предполагая, что это было назначено представлению "item-details", ваш запрос:

https://username.cloudant.com/test/_design/catalogue/_view/item-details?include_docs=true&key=%22656F-PINSEC12%22

должен возвратить

{
   "total_rows":2,
   "offset":0,
   "rows":
   [
       {
          "id":"7b547bae4ac911c6f05b97eba6cb355a",
          "key":"656F-PINSEC12",
          "value":null,
          "doc":{
             "_id": "7b547bae4ac911c6f05b97eba6cb355a",
             "_rev": "4-4fde0cac1b4b8afc618bbba5b6669193",
             "type": "shoe-images",
             "sku": "656F-PINSEC12",
             "color": "Black/Houndstoot",
             "full-images": [
                 "http://www.someurl.com/full/656F-PINSEC12.jpg"
             ],
             "thumbnail-images": [
                  "http://www.someurl.com/thumb/656F-PINSEC12.jpg"
             ]
          }
      },
      {
          "id":"12b6289d558d7ceb5bef725091666ce5",
          "key":"656F-PINSEC12",
          "value":null
          "doc":{
            "_id": "12b6289d558d7ceb5bef725091666ce5",
           "_rev": "2-192df709f9de1ef27e9e5f4404863bcc",
           "type": "shoe-sizes",
           "sku": "656F-PINSEC12",
           "shoe-color": "black/houndstooth",
           "shoe-sizes": [
               {
                   "size": 5,
                   "IsSizeAvailable": true
               },
               {
                   "size": 6,
                   "IsSizeAvailable": true
               },
               {
                   "size": 7,
                   "IsSizeAvailable": true
               },
               {
                   "size": 8,
                   "IsSizeAvailable": true
               },
               {
                   "size": 9,
                   "IsSizeAvailable": true
               },
               {
                   "size": 10,
                   "IsSizeAvailable": true
               },
               {
                   "size": 11,
                   "IsSizeAvailable": true
               },
               {
                   "size": 12,
                   "IsSizeAvailable": true
               },
               {
                   "size": 13,
                   "IsSizeAvailable": true
               },
               {
                   "size": 14,
                   "IsSizeAvailable": true
               }
           ]

        }       
    ] 
}

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

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