elasticsearch3

rbcd / 2023-06-01 / 原文

索引的批量操作

#批量查询: GET /_mget

#批量写入:
POST /<index>/_bulk
{"action": {"metadata"}}
{"data"}

注意:
1、bulk api对json的语法有严格的要求,除了delete外,每一个操作都要两个json串(metadata2和business data),且每个json串内不能换行,非同一个json串必须换行,否则会报错;
2、bulk操作中,任意一个操作失败,是不会影响其他的操作的,但是在返回结果里,会告诉你异常日志

#索引的操作类型
create:如果在PUT数据的时候当前数据已经存在,则数据会被覆盖,如果在PUT的时候加上操作类型create,此时如果数据已存在则会返回失败,因为已经强制指定了操作类型为create,ES就不会再去执行update操作。比如:PUT /pruduct/_create/1/ ( 老版本的语法为 PUT /pruduct/_doc/1/_create )指的就是在索引product中强制创建id为1的数据,如果id为1的数据已存在,则返回失败。
delete:删除文档,ES对文档的删除是懒删除机制,即标记删除。(lazy delete原理)
index:在ES中,写入操作被称为Index,这里Index为动词,即索引数据为将数据创建在ES中的索引,写入数据亦可称之为“索引数据”。可以是创建,也可以是全量替换
update:执行partial update(全量替换,部分替换)

以上四种操作类型均为写操作。ES中的数据写入均发生在Primary Shard,当数据在Primary写入完成之后会同步到相应的Replica Shard。ES的数据写入有两种方式:单个数据写入和批量写入,ES为批量写入数据提供了特有的API:_bulk。

优缺点
    优点:相较于普通的Json格式的数据操作,不会产生额外的内存消耗,性能更好,常用于大数据量的批量写入
    缺点:可读性差,可能会没有智能提示。

使用场景:大数据量的批量操作,比如数据从MySQL中一次性写入ES,批量写入减少了对es的请求次数,降低了内存开销以及对线程的占用。

批量查询
GET product/_mget
{
  "ids": [2,3,4]
}

GET product/_mget
{
  "docs": [{
      "_id": 2,
      "_source": ["name","price"]
    },
    {
      "_id": 3,
      "_source": {
        "include": ["name","price"],
        "exclude": ["price","type"]
      }
    }]
}

创建数据
PUT test_index/_doc/1
{
  "test_field":"test",
  "test_title":"title"
}

删除
DELETE test_index/_doc/3

更新
POST /test_index/_update/11
{
  "doc": {
    "test_title": "test 3"
  }
}

重命名索引
POST _reindex
{
  "source": {"index": "product"},
  "dest": {"index": "product2"}
}

批量新增、修改处理数据
#加?filter_path=items.*.error  只显示失败的
POST /_bulk?filter_path=items.*.error
{ "create": { "_index": "product2",  "_id": "2" }}
{ "name":    "_bulk create 2" }
{ "create": { "_index": "product2",  "_id": "12" }}
{ "name":    "_bulk create 12" }
{ "index":  { "_index": "product2",  "_id": "3" }}
{ "name":    "index product2 "}
{ "index":  { "_index": "product2",  "_id": "13" }}
{ "name":    "index product2" }
{ "update": { "_index": "product2",  "_id": "4","retry_on_conflict" : "3"} }
{ "doc" : {"test_field2" : "bulk test1"} }

模糊查询

#前缀搜索:prefix

概念:以xx开头的搜索,不计算相关度评分。

注意:
    前缀搜索匹配的是term,而不是field。即匹配的是字段分词后的单个term的前缀匹配
    前缀搜索的性能很差,尽量不用
    前缀搜索没有缓存
    前缀搜索尽可能把前缀长度设置的更长

语法:
GET <index>/_search
{
  "query": {
    "prefix": {
      "<field>": {
        "value": "<word_prefix>"
      }
    }
  }
}
默认的前缀匹配长度范围
index_prefixes: "min_chars" : 2,   "max_chars" : 5

GET my_index/_search
{
  "query": {
    "prefix": {
      "text": {
        "value": "城市"
      }
    }
  }
}

索引实例
PUT my_index
{
  "mappings": {
    "properties": {
      "text": {
        "analyzer": "ik_max_word",
        "type": "text",
        "index_prefixes":{
          "min_chars":2,
          "max_chars":4
        },
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}


#通配符:wildcard

概念:通配符运算符是匹配一个或多个字符的占位符。例如,*通配符运算符匹配零个或多个字符。您可以将通配符运算符与其他字符结合使用以创建通配符模式。

注意:通配符匹配的也是term,而不是field

语法:
GET <index>/_search
{
  "query": {
    "wildcard": {
      "<field>": {
        "value": "<word_with_wildcard>"
      }
    }
  }
}

GET my_index/_search
{
  "query": {
    "wildcard": {
      "text.keyword": {
        "value": "my eng*ish"
      }
    }
  }
}

#正则:regexp

概念:regexp查询的性能可以根据提供的正则表达式而有所不同。为了提高性能,应避免使用通配符模式,如.或 .?+未经前缀或后缀

语法:
GET <index>/_search
{
  "query": {
    "regexp": {
      "<field>": {
        "value": "<regex>",
        "flags": "ALL",
      }
    }
  }
}

GET product_en/_search
{
  "query": {
    "regexp": {
      "desc": {
        "value":"[\\s\\S]*nfc[\\s\\S]*",
        "flags": "COMPLEMENT"
      }
    }
  }
}

#模糊查询:fuzzy
混淆字符 (box → fox)
缺少字符 (black → lack)
多出字符 (sic → sick)
颠倒次序 (act → cat)

注意:
    fuzzy和match的区别:fuzzy的搜索字符是不分词的,match的搜索字符是分词的
    大数据量的不建议使用

语法
GET <index>/_search
{
  "query": {
    "fuzzy": {
      "<field>": {
        "value": "<keyword>"
      }
    }
  }
}

# fuzzy:模糊查询
GET product_en/_search
{
  "query": {
    "fuzzy": {
      "desc": {
        "value": "quangongneng nfc",
        "fuzziness": "2"
      }
    }
  }
}


#短语前缀:match_phrase_prefix

match_phrase:
    match_phrase会分词
    被检索字段必须包含match_phrase中的所有词项并且顺序必须是相同的
    被检索字段包含的match_phrase中的词项之间不能有其他词项

match_phrase_prefix:对性能有影响

概念:
match_phrase_prefix与match_phrase相同,但是它多了一个特性,就是它允许在文本的最后一个词项(term)上的前缀匹配,如果 是一个单词,比如a,它会匹配文档字段所有以a开头的文档,如果是一个短语,比如 "this is ma" ,他会先在倒排索引中做以ma做前缀搜索,然后在匹配到的doc中做match_phrase查询,(网上有的说是先match_phrase,然后再进行前缀搜索, 是不对的)

参数
    analyzer 指定何种分析器来对该短语进行分词处理
    max_expansions 限制前缀匹配的最大词项
    boost 用于设置该查询的权重
    slop 允许短语间的词项(term)间隔:slop 参数告诉 match_phrase 查询词条相隔多远时仍然能将文档视为匹配 什么是相隔多远? 意思是说为了让查询和文档匹配你需要移动词条多少次?

GET product_en/_search
{
  "query": {
    "match_phrase_prefix": {
      "desc": {
        "query": "de zhong shouji hongzhaji",
        "max_expansions": 50,
        "slop":3
      }
    }
  }
}

# N-gram和edge ngram