Подтвердить что ты не робот

Вложенные документы в Elasticsearch

Я пишу приложение для управления активами. Он позволяет пользователям хранить произвольные атрибуты активов, добавляя в актив элемент управления html, например текстовое поле, меню выбора и т.д. JSON-представление атрибута затем становится частью документа JSON-ресурса, хранящегося в couchdb. Актив имеет следующую структуру в couchdb:

{
   "_id": "9399fb27448b1e5dfdca0181620418d4",
   "_rev": "12-fa50eae8b50f745f9852e9fab30ef5d9",
   "type": "asset",
   "attributes": [
       {
           "id": "9399fb27448b1e5dfdca01816203d609",
           "type": "text",
           "heading": "Brand",
           "data": "",
           "requiredBySystem": true
       },
       {
           "id": "9399fb27448b1e5dfdca01816203e68e",
           "type": "userSelectMenu",
           "heading": "Assigned To",
           "data": "",
           "requiredBySystem": true
       },
       {
           "id": "9399fb27448b1e5dfdca01816203e9c9",
           "type": "categories",
           "heading": "Categories",
           "data": [
               "0d7e6233e5f48b4f55c5376bf00b1be5",
               "0d7e6233e5f48b4f55c5376bf00d94cf"
           ],
           "requiredBySystem": true
       },
       {
           "id": "9399fb27448b1e5dfdca01816207uy5a",
           "type": "radio",
           "heading": "Radio Buttons",
           "data": [
               {
                   "text": "Button 1",
                   "checked": false
               },
               {
                   "text": "Button 2",
                   "checked": true
               }
           ],
           "requiredBySystem": true
       },
       {
           "id": "9399fb27448b1e5dfdca01816205tgh6",
           "type": "checkboxes",
           "heading": "Checkboxes",
           "data": [
             {
                 "text": "Box 1",
                 "checked": false
             },
             {
                 "text": "Box 2",
                 "checked": true
             }
           ],
           "requiredBySystem": true
       },
       {
           "id": "9399fb27448b1e5dfdca0181620k81gt",
           "type": "select",
           "heading": "Select Menu",
           "data": [
               {
                   "text": "Option 1",
                   "checked": false
               },
               {
                   "text": "Option 2",
                   "checked": true
               }
           ],
           "requiredBySystem": true
       }
   ]
}

Я не уверен, что размещение атрибутов в массиве - лучший способ разрешить поиск актива на основе значения атрибута. Было бы лучше приложить атрибут непосредственно к активу как собственность? Сейчас я экспериментирую в поиске elastics. Если я попытаюсь сохранить документ как есть, elasticsearch вернет ошибку:

"error": "MapperParsingException [Не удалось проанализировать [attributes.data]]; вложен: ElasticSearchIllegalArgumentException [неизвестное свойство [текст]];"

Я использую следующее отображение:

"mappings" : {
    "asset" : {
      "properties" : {
        "_id": {
          "type" : "string",
          "index" : "not_analyzed"
        },
        "_rev": {
          "type" : "string",
          "index" : "not_analyzed"
        },
        "type": {
          "type" : "string",
          "index" : "not_analyzed"
        },
        "attributes": {
          "properties" : {
            "id" : {
              "type" : "string"
            },
            "type" : {
              "type" : "string",
              "index" : "not_analyzed"
            },
            "heading" : {
              "type" : "string"
            },
            "data" : {
              "type" : "string"
            }
          }
        }
      }
    }
  }

Не знаю, где я здесь ошибся. Спасибо за вашу помощь!

Трой

4b9b3361

Ответ 1

Проблема возникает из-за того, как структурирован ваш документ. attribute.data - это строка/массив строк и полный внутренний объект. ES не позволяет изменять тип свойства.

В принципе, у вас не может быть этого:


"data": [
  "0d7e6233e5f48b4f55c5376bf00b1be5",
  "0d7e6233e5f48b4f55c5376bf00d94cf"
],

и это:


"data":[
  {
    "text":"Button 1",
    "checked":false
  },
  {
    "text":"Button 2",
    "checked":true
  }
],

в том же документе. Первый экземпляр data сообщает ES, что "данные представляют собой массив строк". Но тогда второй экземпляр data говорит: "Эй, я объект!", Поэтому ES выдает ошибку.

Вы можете обойти эту проблему, явно объявив data в качестве объекта и установив enabled: false, но это, вероятно, не то решение, которое вы хотите (поскольку это просто говорит ES хранить data как текстовое поле без синтаксического анализа.

Другим вариантом является либо реструктуризация ваших данных, либо разделение data на этот документ (например, сопоставление родителя/ребенка)