Поиск, сортировка и агрегирование документов - PullRequest
1 голос
/ 23 марта 2020

У меня есть база данных с двумя различными типами документов:

{
  "id": "1",
  "type": "User",
  "username": "User 1"
}

и вторым типом документа со следующей структурой:

{
  "id": "2",
  "type": "Asset",
  "name": "Asset one",
  "owner_id": "1"  //id of the user who owns the asset
}

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

Возможно ли то, что мы пытаемся сделать sh, используя CouchDB? Можем ли мы сделать это с помощью поисковых индексов?

Мы используем CouchDB 2.3.1 и не можем выполнить обновление (по крайней мере, на данный момент).

Мне нужно найти username и актив name, а также сможете сортировать по этим полям. Нам не нужен полнофункциональный поиск. Что-то вроде matches (без учета регистра) достаточно хорошо.

Идентификатор / owner_id, указанный в примерах, представляет документ _id. Пользователь не будет владеть более чем ~ 10 активами. Обычный сценарий будет 2/3 активов.

1 Ответ

1 голос
/ 24 марта 2020

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

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

Например, пользовательский документ, где свойство assets содержит набор сведений о собственном активном документе (_id, name):

{
  "_id": "1",
  "type": "User",
  "username": "User 1",
  "assets": [
    [
      "2",
      "Asset one"
    ],
    [
      "10",
      "Asset ten"
    ]
  ]
}

Учитывая эту структуру, документ актива довольно тонкий

{
  "_id": "2", 
  "type": "Asset",
  "name": "Asset one"
}

Я предполагаю, что в документах актива гораздо больше информации, чем представлено.

Итак, как получить поиск и отсортированные результаты? Рассмотрим проект do c _design/user/_view/assets со следующей функцией карты:

function (doc) {
  if(doc.type === "User" && doc.assets) {
    for(var i = 0; i < doc.assets.length; i++) {
      /* emit user name, asset name, value as asset doc id */
      emit(doc.username + '/' + doc.assets[i][1], { _id: doc.assets[i][0] });
      /* emit asset name with leading /, value as User doc _id */
      emit('/' + doc.assets[i][1], { _id: doc._id })
    }
  }
}

Предположим, что в базе данных есть только один пользователь «Пользователь 1» и два документа Актива «Актив один» и «Актив десять» ».

Этот запрос (с использованием cUrl)

curl -G <db endpoint>/_design/user/_view/assets

приводит к

{
  "total_rows":4,"offset":0,"rows":[
    {"id":"1","key":"/Asset one","value":{"_id":"1"}},
    {"id":"1","key":"/Asset ten","value":{"_id":"1"}},
    {"id":"1","key":"User 1/Asset one","value":{"_id":"2"}},
    {"id":"1","key":"User 1/Asset ten","value":{"_id":"10"}}
  ]
}

Не очень интересно, за исключением того, что строки возвращаются в порядке возрастания в соответствии с key , Чтобы изменить порядок, просто добавив параметр descending=true

curl -G <db endpoint>/_design/user/_view/assets?descending=true

, получим

{
  "total_rows":4,"offset":0,"rows":[
    {"id":"1","key":"User 1/Asset ten","value":{"_id":"10"}},
    {"id":"1","key":"User 1/Asset one","value":{"_id":"2"}},
    {"id":"1","key":"/Asset ten","value":{"_id":"1"}},
    {"id":"1","key":"/Asset one","value":{"_id":"1"}}
  ]
}

Теперь вот где все становится прохладно, и эти классные вещи - startkey и endkey.

Для определения природы ключей мы можем запросить все активы для «пользователя 1» и получить документы активов, возвращенные в упорядоченном порядке в соответствии с именем ресурса, используя sla sh в ключе

 curl -G <db endpoint>/_design/user/_view/assets 
 -d "startkey="""User%201/"""" -d "endkey="""User%201/\uFFF0""""

примечание Я нахожусь на Windows, где мы должны избегать двойных кавычек; (

приводит к

{
  "total_rows":4,"offset":2,"rows":[
    {"id":"1","key":"User 1/Asset one","value":{"_id":"2"}},
    {"id":"1","key":"User 1/Asset ten","value":{"_id":"10"}}
  ]
}

Это поиск префикса . Обратите внимание на использование символа высокого юникода \ uFFF0 в качестве терминатора; мы просим все документы в представлении, которые начинаются с "User 1 /".

Аналогично, чтобы получить отсортированный список всех активов

curl -G <db endpoint>/_design/user/_view/assets 
-d "startkey="""/"""" -d "endkey="""/\uFFF0""""

дает

{
  "total_rows":4,"offset":0,"rows":[
    {"id":"1","key":"/Asset one","value":{"_id":"1"}},
    {"id":"1","key":"/Asset ten","value":{"_id":"1"}}
  ]
}

Поскольку _id документа актива emit'ed, используйте include_docs для получения документа актива:

 curl -G <db endpoint>_design/user/_view/assets -d "include_docs=true"  
 -d "startkey="""User%201/"""" -d "endkey="""User%201/\uFFF0""""

доходность

{
  "total_rows": 4,
  "offset": 2,
  "rows": [
    {
      "id": "1",
      "key": "User 1/Asset one",
      "value": {
        "_id": "2"
      },
      "doc": {
        "_id": "2",
        "_rev": "2-f4e78c52b04b77e4b5d2787c21053155",
        "type": "Asset",
        "name": "Asset one"
      }
    },
    {
      "id": "1",
      "key": "User 1/Asset ten",
      "value": {
        "_id": "10"
      },
      "doc": {
        "_id": "10",
        "_rev": "2-30cf9245b2f3e95f22a06cee6789d91d",
        "type": "Asset",
        "name": "Asset 10"
      }
    }
  ]
}

То же самое относится и к активам, в которых отправляется _id пользователя.

Caveat

Основной недостаток заключается в том, что удаление документа актива требует обновления документа пользователя; не конец света, но было бы очень приятно избежать этой зависимости.

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

Надеюсь, вышесказанное вдохновляет на решение. Удачи!

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