您的位置:首页 > 数据库

Elasticsearch 常用查询语句理解

2017-01-16 15:16 344 查看
pretty

在任意的查询字符串中增加pretty参数,会让Elasticsearch美化输出(pretty-print)JSON响应以便更加容易阅读。

GET /website/blog/123?pretty

针对性过滤输出

GET /website/blog/123?_source=title,text

如果你想做的只是检查文档是否存在,使用HEAD方法来代替GET。HEAD请求不会返回响应体,只有HTTP头:

curl -i -XHEAD http://localhost:9200/website/blog/123
HTTP/1.1 200 OK

Content-Type: text/plain; charset=UTF-8

Content-Length: 0

请求成功的创建了一个新文档,Elasticsearch将返回正常的元数据且响应状态码是201 Created,如果文档已存在,Elasticsearch将返回409 Conflict响应状态码。

解决冲突:

1.在读一行数据前锁定这行,然后确保只有加锁的那个线程可以修改这行数据。

2.在读写过程中数据发生了变化,更新操作将失败。这时候由程序决定在失败后如何解决冲突。实际情况中,可以重新尝试更新,刷新数据(重新读取)或者直接反馈给用户。

如果需要从Elasticsearch中检索多个文档,相对于一个一个的检索,更快的方式是在一个请求中使用multi-get或者mget API。mget是针对读,针对所有主从分片。

POST /_mget

{

   "docs" : [

      {

         "_index" : "website",

         "_type" :  "blog",

         "_id" :    2

      },

      {

         "_index" : "website",

         "_type" :  "pageviews",

         "_id" :    1,

         "_source": "views"

      }

   ]

}

bulk API允许我们使用单一请求来实现多个文档的create、index、update或delete。针对主分片操作。

POST /_bulk

{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}

{ "title":    "Cannot create - it already exists" }

{ "index":  { "_index": "website", "_type": "blog", "_id": "123" }}

{ "title":    "But we can update it" }

整个批量请求需要被加载到接受我们请求节点的内存里,所以请求越大,给其它请求可用的内存就越小。有一个最佳的bulk请求大小。超过这个大小,性能不再提升而且可能降低。

路由文档到分片

当你索引一个文档,它被存储在单独一个主分片上。Elasticsearch是如何知道文档属于哪个分片的呢?当你创建一个新文档,它是如何知道是应该存储在分片1还是分片2上的呢?

进程不能是随机的,因为我们将来要检索文档。事实上,它根据一个简单的算法决定:

shard = hash(routing) % number_of_primary_shards

routing值是一个任意字符串,它默认是_id但也可以自定义。这个routing字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数(remainder),余数的范围永远是0到

number_of_primary_shards - 1,这个数字就是特定文档所在的分片。

这也解释了为什么主分片的数量只能在创建索引时定义且不能修改:如果主分片的数量在未来改变了,所有先前的路由值就失效了,文档也就永远找不到了。

replication复制

复制默认的值是sync。这将导致主分片得到复制分片的成功响应后才返回。设置replication为async,请求在主分片上被执行后就会返回给客户端。它依旧会转发请求给复制节点,但将不知道复制

节点成功与否。

consistency

默认主分片在尝试写入时需要规定数量(quorum)或过半的分片(可以是主节点或复制节点)可用。

int( (primary + number_of_replicas) / 2 ) + 1  number_of_replicas是复制分片的数量。

数据检索

1.客户端给Node 1发送get请求。

2.节点使用文档的_id确定文档属于分片0。分片0对应的复制分片在三个节点上都有。负载均衡转发请求到Node 2。

3.Node 2返回文档(document)给Node 1然后返回给客户端。

搜索:

hits:响应中最重要的部分是hits,它包含了total字段来表示匹配到的文档总数,hits数组还包含了匹配到的前10条数据。每个节点都有一个_score字段,这是相关性得分(relevance score),

它衡量了文档与查询的匹配程度。按照_score降序排列的

took告诉我们整个搜索请求花费的毫秒数。

time_out值告诉我们查询超时与否。

{

   "hits" : {

      "total" :       14,

      "hits" : [

        {

          "_index":   "us",

          "_type":    "tweet",

          "_id":      "7",

          "_score":   1,

          "_source": {

             "date":    "2014-09-17",

             "name":    "John Smith",

             "tweet":   "The Query DSL is really powerful and flexible",

             "user_id": 2

          }

       },

        ... 9 RESULTS REMOVED ...

      ],

      "max_score" :   1

   },

   "took" :           4,

   "_shards" : {

      "failed" :      0,

      "successful" :  10,

      "total" :       10

   },

   "timed_out" :      false

}

多索引和多类别:

GET /_all/tweet/_search?q=tweet:elasticsearch    _all:所有文档

/_search

在所有索引的所有类型中搜索

/gb/_search

在索引gb的所有类型中搜索

/gb,us/_search

在索引gb和us的所有类型中搜索

/g*,u*/_search

在以g或u开头的索引的所有类型中搜索

Elasticsearch分页展示,接受from和size参数:

size: 结果数,默认10

from: 跳过开始的结果数,默认0

如果你想每页显示5个结果,页码从1到3,那请求如下:

GET /_search?size=5

GET /_search?size=5&from=5

GET /_search?size=5&from=10

映射(mapping)机制用于进行字段类型确认,将每个字段匹配为一种确定的数据类型(string, number, booleans, date等)。

分析(analysis)机制用于进行全文文本(Full Text)的分词,以建立供搜索用的反向索引。

例:Elasticsearch在对gb索引中的tweet类型进行mapping,Elasticsearch为对字段类型进行猜测,动态生成了字段和类型的映射关系

date类型的字段和string类型的字段的索引方式是不同的,查询匹配日期结果也是不同的。

{

   "gb": {

      "mappings": {

         "tweet": {

            "properties": {

               "date": {

                  "type": "date",

                  "format": "dateOptionalTime"

               },

               "name": {

                  "type": "string"

               },

               "tweet": {

                  "type": "string"

               },

               "user_id": {

                  "type": "long"

               }

            }

         }

      }

   }

}

Elasticsearch中的数据可以大致分为两种类型:

确切值确定的,正如它的名字一样。比如一个date或用户ID,确切值"Foo"和"foo"就并不相同。确切值2014和2014-09-15也不相同。

全文文本,文本化的数据,全文文本常常被称为非结构化数据,匹配程度查询,例如一封邮件

分析器:

当你查询全文(full text)字段,查询将使用相同的分析器来分析查询字符串,以产生正确的词列表。全文检索需要分词。

当你查询一个确切值(exact value)字段,查询将不分析查询字符串,但是你可以自己指定。确切值查询不需要分词。

Elasticsearch支持以下简单字段类型:

类型             表示的数据类型

String             string

Whole number     byte, short, integer, long

Floating point     float, double

Boolean     boolean

Date             date

查看映射:

GET /gb/_mapping/tweet

index值             解释

analyzed     首先分析这个字符串,然后索引。换言之,以全文形式索引此字段。

not_analyzed     索引这个字段,使之可以被搜索,但是索引内容和指定值一样。不分析此字段。

no             不索引这个字段。这个字段不能为搜索到。

string类型字段默认值是analyzed。如果我们想映射字段为确切值,我们需要设置它为not_analyzed:

{

    "tag": {

        "type":     "string",

        "index":    "not_analyzed"

    }

}

叶子子句(leaf clauses)(比如match子句)用以在将查询字符串与一个字段(或多字段)进行比较

复合子句(compound)用以合并其他的子句。例如,bool子句允许你合并其他的合法子句,must,must_not或者should,如果可能的话:

{

    "bool": {

        "must":     { "match": { "tweet": "elasticsearch" }},

        "must_not": { "match": { "name":  "mary" }},

        "should":   { "match": { "tweet": "full text" }}

    }

}

must :: 多个查询条件的完全匹配,相当于 and。

must_not :: 多个查询条件的相反匹配,相当于 not。

should :: 至少有一个查询条件匹配, 相当于 or。

结构化查询(Query DSL)查询语句会询问每个文档的字段值与特定值的匹配程度如何

结构化过滤(Filter DSL)一条过滤语句会询问每个文档的字段值是否包含着特定值

最常用到的查询过滤语句:

term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed的字符串(未经分析的文本数据类型)

terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。

range过滤允许我们按照指定范围查找一批数据

范围操作符包含:

gt :: 大于

gte:: 大于等于

lt :: 小于

lte:: 小于等于

exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段

validate API 可以验证一条查询语句是否合法。

GET /gb/tweet/_validate/query

{

   "query": {

      "tweet" : {

         "match" : "really powerful"

      }

   }

}

以上请求的返回值告诉我们这条语句是非法的:

{

  "valid" :         false,

  "_shards" : {

    "total" :       1,

    "successful" :  1,

    "failed" :      0

  }

}

理解查询语句:使用 explain 参数可以返回一个带有查询语句的可阅读描述

GET /_validate/query?explain

{

   "query": {

      "match" : {

         "tweet" : "really powerful"

      }

   }

}

explanation 会为每一个索引返回一段描述,因为每个索引会有不同的映射关系和分析器:

{

  "valid" :         true,

  "_shards" :       { ... },

  "explanations" : [ {

    "index" :       "us",

    "valid" :       true,

    "explanation" : "tweet:really tweet:powerful"

  }, {

    "index" :       "gb",

    "valid" :       true,

    "explanation" : "tweet:really tweet:power"

  } ]

}

【原创】原创文章,更多关注敬请关注微信公众号。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息