小言_互联网的博客

Elasticsearch:避免不必要的脚本 - scripting

517人阅读  评论(0)

Painless 脚本为我们的搜索带来了很多的方便和灵活性,但是在很多的实践中,我们需要认真地思考这个脚本是不是最有效的。特别是,当我们在 query 使用脚本时,我们需要特别注意。这是因为在搜索时,需要针对每个文档进行计算,当我们的文档的数量很大时,那么这个计算量将会是非常大,从而影响搜索的效率。
 

比如,我们创建如下的一个文档:


  
  1. PUT twitter /_doc/ 1
  2. {
  3. "user" : "双榆树-张三",
  4. "message" : "今儿天气不错啊,出去转转去",
  5. "uid" : 2,
  6. "age" : 20,
  7. "city" : "北京",
  8. "province" : "北京",
  9. "country" : "中国",
  10. "address" : "中国北京市海淀区",
  11. "location" : {
  12. "lat" : "39.970718",
  13. "lon" : "116.325747"
  14. }
  15. }

假如我们想搜索 message 字段的长度大于 10 的所有文档,我们可以通过如下的方法来获得。


  
  1. GET twitter/_search
  2. {
  3. "query": {
  4. "script": {
  5. "script": {
  6. "lang": "painless",
  7. "source": "doc['message.keyword'].value.length() > params.length",
  8. "params": {
  9. "length": 10
  10. }
  11. }
  12. }
  13. }
  14. }

在上面我们使用脚本来计算 message 字段的长度,并返回所有 message 字段长度超过 10 的文档。

上面的搜索咋一看,没有任何毛病,但是假设我们的文档数目有很多(比如几万个数据),那么上面的这个在搜索时的计算量将是非常大的,从而会影响搜索的效率。那么我们有什么好的方法来解决这个问题呢?

我们可以把这个计算放到 index 时候,也就是在建立索引的时候。比如我们可以这么做:


  
  1. DELETE twitter
  2. PUT _ingest/pipeline/calculate_length
  3. {
  4. "description": "Calculate the length of message",
  5. "processors": [
  6. {
  7. "script": {
  8. "source": """
  9. ctx.length = ctx.message.length()
  10. """
  11. }
  12. }
  13. ]
  14. }

在上面,我们先删除之前创建的 twitter 索引,然后创建一个计算 message 字段长度的一个脚本 processor。在导入一个文档时,我们使用如下的方法:


  
  1. PUT twitter /_doc/ 1?pipeline=calculate_length
  2. {
  3. "user": "双榆树-张三",
  4. "message": "今儿天气不错啊,出去转转去",
  5. "uid": 2,
  6. "age": 20,
  7. "city": "北京",
  8. "province": "北京",
  9. "country": "中国",
  10. "address": "中国北京市海淀区",
  11. "location": {
  12. "lat": "39.970718",
  13. "lon": "116.325747"
  14. }
  15. }

由于我们使用了 calculate_length 这个 pipeline,那么它将会为我们创建一个新的叫做 length 的字段。我们通过如下的方法来进行查询:

GET twitter/_search

上面显示的结果为:


  
  1. {
  2. "took" : 0,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 1,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 1.0,
  16. "hits" : [
  17. {
  18. "_index" : "twitter",
  19. "_type" : "_doc",
  20. "_id" : "1",
  21. "_score" : 1.0,
  22. "_source" : {
  23. "country" : "中国",
  24. "address" : "中国北京市海淀区",
  25. "city" : "北京",
  26. "length" : 13,
  27. "message" : "今儿天气不错啊,出去转转去",
  28. "uid" : 2,
  29. "province" : "北京",
  30. "location" : {
  31. "lon" : "116.325747",
  32. "lat" : "39.970718"
  33. },
  34. "user" : "双榆树-张三",
  35. "age" : 20
  36. }
  37. }
  38. ]
  39. }
  40. }

我们可以看到一个新增加的 length 字段。上面显示的值为 13 。那么有了这个字段,我们就可以通过如下的方法来进行查询了:


  
  1. GET twitter/_search
  2. {
  3. "query": {
  4. "range": {
  5. "length": {
  6. "gte": 10
  7. }
  8. }
  9. }
  10. }

在上面,我们使用了新增加的 length 字段来查询我们的文档。这样可以大大地提供搜索的效率。


转载:https://blog.csdn.net/UbuntuTouch/article/details/108061204
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场