Elasticsearch中的嵌套文档

时间:2013-03-23 03:29:56

标签: elasticsearch

我正在编写资产管理应用程序。它允许用户通过向资产添加html控件(如文本字段,选择菜单等)来存储任意资产属性。然后,该属性的JSON表示将成为存储在couchdb中的资产JSON文档的一部分。资产在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
       }
   ]
}

我不确定在数组中放置属性是否是允许基于属性值搜索资产的最佳方式。将属性作为属性直接附加到资产会更好吗?我现在在弹性搜索中进行实验。如果我尝试按原样存储文档,elasticsearch将返回错误:

“error”:“MapperParsingException [无法解析[attributes.data]];嵌套:ElasticSearchIllegalArgumentException [未知属性[text]];”

我正在使用以下映射:

"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"
            }
          }
        }
      }
    }
  }

不知道我在哪里错了。谢谢你的帮助!

特洛伊

1 个答案:

答案 0 :(得分:26)

问题源于文档的结构方式。 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存储{ {1}}作为文本字段,没有解析。

另一种选择是重组数据,或将data拆分成文档(例如父/子映射)