【问题标题】:Dynamic Mapping for an object field that unwraps the parent path展开父路径的对象字段的动态映射
【发布时间】:2014-05-23 01:46:52
【问题描述】:

我正在评估 ElasticSearch 是否能够满足我正在构建的新系统的需求。它看起来很棒,所以我真的希望我能找到一个可行的映射策略。

在该系统中,管理员可以动态定义与文档关联的字段。所以一个给定的类型(在弹性搜索这个词的意义上)可以有任意数量的字段,我不知道提前的名字。并且每个字段可以是任何类型:int、日期、字符串等。

示例文档可能如下所示:

{
    "name": "bob",
    "age": 22,
    "title": "Vice Intern",
    "tagline": "Ask not what your company can do for you, but..."
}

请注意,有 2 个字符串字段。惊人的。我的问题是我想要分析“标语”,但我不想分析“标题”。

请记住,我事先并不知道这些字段的名称。并且每种类型可能有多个字段。所以可能有 10 个不同名称的字符串字段,其中 3 个应该分析,7 个不应该分析。

我的另一个要求是管理员提供的字段名称也应该是他们可以搜索的名称。因此,例如,如果他们想找到所有有话要说的副实习生,那么 lucene 查询可能是:

+title:"Vice Intern" +tagline:"company"

所以我的想法是我可以定义一个动态映射。由于我不提前知道字段的名称,这似乎是一个很好的方法。关键是想出一种方法来区分应该分析的字符串字段和不应该分析的字符串字段!

我想,嘿,我把所有需要分析的字段都放到一个嵌套对象中,像这样:

{
    "name": "bob",
    "age": 22,
    "title": "Vice Intern",
    "textfields": {
        "tagline": "Ask not what your company can do for you, but...",
        "somethingelse": "lorem ipsum",
    }
}    

然后,在我的动态映射中,我有一种不同方式映射这些字段:

{
    "mytype": {
        "dynamic_templates": {
            "nested_textfields": {
                "match": "textfields",
                "match_mapping_type": "string",
                "mapping": {
                    "index": "analyzed",
                    "analyzer": "default"
                }
            }
        }
    }
}

我知道这是不对的,我实际上需要某种嵌套映射,但没关系,因为如果我理解正确,即使我得到了它,也意味着搜索这些字段(通过 lucene 语法) 像这样:

+title:"Vice Intern" +textfields.tagline:"company"

而且我不想要“textfields”前缀。由于我是提供包装文本字段的 textfields 对象的人,因此我知道其中的字段在整个文档中仍然是唯一命名的。

我想改用模式匹配。因此,与其将它们包装在“textfields”对象中,我可以为它们添加前缀,例如“textfield_tagline”。但是当这样做时,动态映射中的 {name} 标记包含前缀,我看不到仅拉出“*”部分的方法。

任何能让我获得必要行为的解决方案都是正确的答案。即使这涉及到文档本身的嵌套映射信息(你能做到吗?我见过类似的东西,我想......)。

编辑:

我尝试了以下动态模板。我正在尝试使用 index_name 删除“文本字段”。在索引中。不过,这个动态模板似乎并不匹配,因为在放置文档并查看映射后,我没有看到指定的分析器。

    {
        "mytype" : {
            "dynamic_templates":
            [
            {
                "textfields": {
                    "path_match": "textfields.*",
                    "match_mapping_type" : "string",
                    "mapping": {
                        "type": "string",
                        "index": "analyzed",
                        "analyzer": "default",
                        "index_name": "{name}",
                        "fields": {                 
                            "sort": {
                                "type": "string",
                                "index": "not_analyzed",
                                "index_name": "{name}_sort"
                            }
                        }
                    }
                }
            }
            ]
        }
    }

【问题讨论】:

  • 我正在学习嵌套映射和 index_name。似乎我应该能够通过指定它的 index_name 来给嵌套属性(textfields.tagline)一个根级索引名称。还没想好……

标签: elasticsearch


【解决方案1】:

通过以下索引创建(使用映射)、文档和搜索查询,我能够复制您专门要求的结果。类型确实有所不同,但它符合示例的目的。

索引设置

PUT http://localhost:9200/sandbox

{
 "settings": { 
   "index": {
     "number_of_shards": 1,
     "number_of_replicas": 0
   }
 },
 "mappings": {
   "mytype": {
     "dynamic_templates": [
        {
            "indexedfields": {
                "path_match": "indexedfields.*",
                "match_mapping_type" : "string",
                "mapping": {
                    "type": "string",
                    "index": "analyzed",
                    "analyzer": "default",
                    "index_name": "{name}",
                    "fields": {                 
                        "sort": {
                            "type": "string",
                            "index": "not_analyzed",
                            "index_name": "{name}_sort"
                        }
                    }
                }
            }
        },
        {
            "textfields": {
                "path_match": "textfields.*",
                "match_mapping_type" : "string",
                "mapping": {
                    "type": "string",
                    "index": "not_analyzed",
                    "index_name": "{name}"
                }
            }
        },
        {
            "strings": {
                "path_match": "*",
                "match_mapping_type" : "string",
                "mapping": {
                    "type": "string",
                    "index": "not_analyzed"
                }
            }

        }
     ]
   }
 }
}

文档

PUT http://localhost:9200/sandbox/mytype/1
{
   "indexedfields":{
      "hello":"Hello world",
      "message":"The great balls of the world are on fire"
   },
   "textfields":{
      "username":"User Name",
      "projectname":"Project Name"
   }
}

搜索

POST http://localhost:9200/sandbox/mytype/_search
{
  "query": {
    "query_string": {
      "query": "message:\"great balls\""
    }
  },
   "filter":{
      "query":{
         "query_string":{
            "query":"username:\"User Name\""
         }
      }
   },
   "from":0,
   "size":10,
   "sort":[

   ]
}

搜索返回以下响应:

{
   "took":2,
   "timed_out":false,
   "_shards":{
      "total":1,
      "successful":1,
      "failed":0
   },
   "hits":{
      "total":1,
      "max_score":0.19178301,
      "hits":[
         {
            "_index":"sandbox",
            "_type":"mytype",
            "_id":"1",
            "_score":0.19178301,
            "_source":{
               "indexedfields":{
                  "hello":"Hello world",
                  "message":"The great balls of the world are on fire"
               },
               "textfields":{
                  "username":"User Name",
                  "projectname":"Project Name"
               }
            }
         }
      ]
   }
}

【讨论】:

  • 太棒了。看来我已经通过 index_name 事情弄清楚了。我认为它不起作用,因为当我得到生成的 _mapping 时,没有“索引”映射,只有非索引映射。但正如你离线告诉我的那样,这只是因为这是默认设置,它忽略了默认设置。太棒了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多