美文网首页
使用 Elasticsearch nested 可能会遇到的疑问

使用 Elasticsearch nested 可能会遇到的疑问

作者: bysir | 来源:发表于2019-11-17 18:40 被阅读0次

    什么是nested类型

    在理解nested类型之前, 我们还需要理解object类型, 所以你需要看查看以下两个官方文档:

    Elasticsearch中的文档支持存储嵌套的json结构, 如

    {
      "group" : "fans",
      "user" : [ 
        {
          "first" : "John",
          "last" :  "Smith"
        },
        {
          "first" : "Alice",
          "last" :  "White"
        }
      ]
    }
    

    如果我们将以上json插入到文档中, user字段会被dynamic mapping为object类型

    现在 user下的first字段也能被索引到, 但object类型有一个特性是会将数据拍扁为以下结构:

    {
      "group" :        "fans",
      "user.first" : [ "alice", "john" ],
      "user.last" :  [ "smith", "white" ]
    }
    

    可以看到, first和last(也就是alice和white)没有了关联关系, 在query的时候就不会返回期望的结果.

    现在就需要nested上场了, 如果user是nested类型, 那么数据将会被独立为多个独立文档以保障嵌套字段间的关系.

    {
      "user.first" : "alice",
      "user.last" :  "white"
    }
    {
      "user.first" : "john",
      "user.last" :  "smith"
    }
    

    不过从官网文档上来讲, nested类型只适用于优化数组, 而对object没用, 也就是说 如果上例中的users是一个对象, 而不是数组时, 那还不如直接使用object类型, 因为nested的查询会更麻烦.

    使用nested

    上面也说到, 如果使用默认的dynamic mapping, json对象会被匹配为object类型, 如果要使用nested你就需要再创建Index的时候指定mapping

    值得注意的是在查询嵌套结构的时候也和普通的query不同, 需要使用到nested-query

    例如一个文档的mapping是这样的:

    {
        "mappings": {
            "type1" : {
                "properties" : {
                    "obj1" : {
                        "type" : "nested"
                    }
                }
            }
        }
    }
    

    就需要这样写query语句

    {
        "query": {
            "nested" : {
                "path" : "obj1",
                "query" : {
                    "bool" : {
                        "must" : [
                            { "match" : {"obj1.name" : "blue"} },
                            { "range" : {"obj1.count" : {"gt" : 5}} }
                        ]
                    }
                }
            }
        }
    }
    

    Dynamic templates

    当动态添加字段的时候Elasticsearch会自动推断类型, 如string就会使用text类型存储.

    但如果你需要修改这个逻辑就需要使用到dynamic templates.

    比如在上面的例子中, 我们需要对动态添加的user.first字段进行精确搜索, 而不是全文搜索, 就需要使用到keyword类型, 另外的, 我们希望所有字段都是keyword类型(所有用户都可能用某个字段, 如果这个字段被固定了一个类型那么另一个用户可能会插入不成功) 为了达到这个目的, 我们可以这样写dynamic_templates.

    PUT my_index
    {
      "mappings": {
        "my_type": {
          "dynamic_templates": [
            {
              "keywords": {
                "match": "*",
                "mapping": {
                  "type": "keyword"
                }
              }
            }
          ]
        }
      }
    }
    

    当然这个用法只是dynamic_template的冰山一角, 更多用法请参考官方文档 - Dynamic templates

    text 与 keyword 类型

    text datatype是我们最常用的类型, 可以用来实现全文搜索, 原理是在入库的时候text类型的字段会被analyzer(分析器)分割成多个terms再被索引, 这也是实现Inverted index(倒排索引)步骤之一.

    keyword datatype和text不同的时候, keyword不会被分析, 所有的内容都将被存储为一个term. 它通常被用于 过滤, 排序, 聚合, 而不是搜索.

    你可以在文档 - term-qury中找到Why doesn’t the term query match my document?段来理解什么是analyzer, keyword, text.

    相关文章

      网友评论

          本文标题:使用 Elasticsearch nested 可能会遇到的疑问

          本文链接:https://www.haomeiwen.com/subject/emopictx.html