所有由zhufenghua发布的文章

elasticSearch查询等于多个值

已知存在 service 字段(keyword),则查询 service=’shop’ OR service=’waimai’,

则传递数组 [“shop”, “waimai”]

GET index_name/_search
{
  	"query": {
		"terms": {
			"service": [
				"shop",
				"waimai"
			]
		}
	}
}

多个值过滤,filter => bool=> must => terms =>[ ‘name’ => array($val1,$val2)];

elasticSearch使用原生sql查询

使用sql进行查询:(6.3版本以后)

POST /_sql?format=txt
{
    "query": "SELECT * FROM library WHERE release_date < '2000-01-01'"
}

把sql翻译为 DSL

POST /_sql/translate
{
  "query": "SELECT * from index_name where (service='shop' OR service='waimai') LIMIT 10"
}

响应结果:

{
  "size" : 10,
  "query" : {
    "terms" : {
      "service" : [
        "shop",
        "waimai"
      ],
      "boost" : 1.0
    }
  }
}

得到的DSL可能效率不高,甚至可能不完全正确,毕竟是自动生成的,在一定情况下或许有帮助。

elasticSearch-php使用 match_all 时报错:[match_all] query malformed, no start_object after query name

错误翻译结果:[match_all] 查询格式错误,查询名称后没有 start_object

在控制台中,使用的查询是正确的,如下:

GET index_name/_search
{
    "query": {
        "has_child" : {
            "type" : "product",
            "query" : {
                "match_all" : {}  // 注意这个空的 {}
            },
            "min_children": 1, 
            "score_mode" : "min",
            "inner_hits": {
              "size": 5
            }
        }
    }
}

不过需要注意了,match_all 后面是一个空对象。

PHP是采用数组的方式拼接DSL,不能有空数组,因为问题就在于 PHP 会自动把 “content” : {} 转换成 “content” : [] ,在 Elasticsearch DSL 中这样的数据格式是非法的。我们需要告诉 PHP 那个空对象就是一个空对象而非空数组。

修改办法一:

"match_all"=> new \stdClass()

修改办法二:

"match_all"=> (object)[]

php 函数 session_id()

session_id() 可以用来获取/设置 当前会话 ID。

为了能够将会话 ID 很方便的附加到 URL 之后, 你可以使用常量 SID 获取以字符串格式表达的会话名称和 ID

session_id() 实例:

<?php

  session_id("aa");//设置session_id 

  session_start();//开启session会话

  echo session_id();

  // 输出 aa
?>

elasticSearch使用 exists 搜索过滤空内容

在存储时,如果数据不合法,全部改为 null。

在搜索时,对某个字段为空进行校验,如果该字段我为null,则过滤:

{
  "query": {
    "bool": {
      "must": {
        "exists": {
          "field": "字段名"
        }
      }
    }
  }
}

反之,取所有该字段为 null 的数据

{
  "query": {
    "bool": {
      "must_not": {
        "exists": {
          "field": "字段名"
        }
      }
    }
  }
}

elasticSearch分片大小

官方推荐单分片大小为 20-40GB,不超过50GB

  • 按群尾号 % 100 把数据分为 100 个索引
  • 每个索引 12 个分片
  • 每 40000W(120GB)发生一次 Rollover
  • 单个分片最大大小 10GB

耗时情况

  • 插入:~ 25ms
  • 更新:~ 15ms
  • 聚合:200ms 以内

elasticSearch创建父子文档

父子文档,适合子文档频繁更新的情况。

比如一个商家对应多个商品。而商家可能有几千个,每个商家又有几千个商品。

这种情况下,嵌套类型是不可取的,只能使用父子文档,它相当于 sql 中的 join。

mappings 的 字段

'tables_join'=>[  // 维护父子文档字段
     'type'=>'join',
     'relations'=>[
              "store"=>"product",  //  商家、商品   ---- 如果是一父多子,后者改为数组即可,如 "store"=>["product","comment"]
              ]
     ]

在 mappings 中,添加一个字段(名称随意,这里用 tables_join),用于维护父子关系。

上面的 store 就是父文档,而 product 就是子文档。

插入父文档:

"tables_join" : "store"

只需要指定一个属性即可,也就是把 tables_join 指定为前面指定的父文档。

插入子文档:

POST /index_name/_doc/shop_product_1305?routing=1   //必须要带 rounting,且和父文档的routing一致
{
    "other" : "value", // 其他字段
    "tables_join" : {  // 要添加的字段
       "name" : "product",
       "parent" : "shop_store_111"
    }
}

首先 :shop_product_1305 是当前商品的 id,也就是指定了商品 id,而父文档的 id 是 shop_store_111.

另外,tables_join 还有一个字段,就是 name ,这里的 name 就是前面指定的子文档的名称。

最后,有个坑,就是添加子文档的请求必须带 routing,这个 routing 是分片标识,如果从未指定或修改则默认情况下是 1,注意父文档的分片、和子文档的分片必须是同一个分片。

elasticSearch父子文档3种查询

基于父子文档的查询主要有三种:

  • parent_id : 基于父文档 ID 查询所有的子文档
  • has_parent:基于符合条件的父文档的所有子文档
  • has_child : 查询符合条件的子文档的所有父文档

对于第三个查询,实际可以同时返回父子文档,也就是添加 inner_hits 参数。

elasticSearch父子文档同时匹配条件

假设有酒店和房间,是父子文档

查询酒店(只返回父文档)(查询店铺名称中带”客栈“,房间名称带有“小虫子”的{店铺})

POST bnb_home/_search

{
    "query": {
      "bool":{
        "must":[
          {"match":{"data.shopName":"客栈"}},
          {
              "has_child" : {
                  "type" : "room",
                  "query" : {
                    "bool":{
                      "must":[
                        {"match":{"data.roomName":"小虫子"}}
                      ]
                    }
                  }
              }
          }
        ]
      }
    }
}

如果要对子文档的数量进行筛选,则使用 min_children ,以及 max_children 进行筛选。

如果希望对子文档进行更高的评分,可以使用:score_mode : max

查询酒店房间(只返回子文档)(查询店铺名称中带”客栈“,房间名称带有“小虫”的{房间})

POST bnb_home/_search

{
    "query": {
      "bool":{
        "must":[
          {"match":{"data.roomName":"小虫"}},
          {
              "has_parent" : {
                  "parent_type" : "shop",
                  "query" : {
                    "bool":{
                      "must":[
                          {"match":{"data.shopName":"客栈"}}
                      ]
                    }
                  }
              }
          }
        ]
      }
    }
}

如果希望同时返回,则带参数 inner_hits 。