首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于可用性的Elasticsearch无痛脚本搜索文档

基于可用性的Elasticsearch无痛脚本搜索文档
EN

Stack Overflow用户
提问于 2019-09-17 15:00:25
回答 1查看 1.2K关注 0票数 1

我使用的是ES 7.0版。我有一个商店的索引与可用性(开业和关门时间)在UTC时间。我将时间存储在Integer中,这样就可以很容易地在无痛脚本中匹配当前时间。

下面是一个示例文档:

代码语言:javascript
运行
复制
{
          "availability" : {
            "thu" : [
              {
                "start" : 0,
                "end" : 400
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "tue" : [
              {
                "start" : 1300,
                "end" : 2400
              },
              {
                "start" : 0,
                "end" : 400
              }
            ],
            "wed" : [
              {
                "start" : 0,
                "end" : 400
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "sat" : [
              {
                "start" : 1400,
                "end" : 2400
              },
              {
                "start" : 0,
                "end" : 500
              }
            ],
            "fri" : [
              {
                "start" : 0,
                "end" : 400
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "mon" : [
              {
                "start" : 0,
                "end" : 200
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "sun" : [
              {
                "start" : 1400,
                "end" : 2400
              },
              {
                "start" : 0,
                "end" : 200
              }
            ]
          },

.
.
.
.
    }

以下是使用无痛脚本的查询:

代码语言:javascript
运行
复制
GET stores/_search
{
  "query": {
    "bool": {
      "filter" : {
        "script" : {
          "script" : {
            "source": "String d = params.day, start_key = 'availability.'+d+'.start', end_key = 'availability.'+d+'.end'; long t = params.time; if(doc[start_key].size() != 0 && doc[end_key].size() != 0){ long s =  doc[start_key].value; long e = doc[end_key].value; return (s <= t && e > t); }",
            "lang": "painless",
            "params" : {
                "day" : "wed",
                "time" : 300
              }
          }
        }
      }
    }
  }
}

上面的查询正在为星期三的时间300工作,并在结果中给出了上面的文档,但在星期三的时间1400没有工作。看起来脚本总是匹配可用性数组中的第一个值。

我还尝试遍历当天的可用性,但这没有给我任何字段找到错误。

代码语言:javascript
运行
复制
GET stores/_search
{
  "query": {
    "bool": {
      "filter" : {
        "script" : {
          "script" : {
            "source": "String d = params.day, start_key = 'availability.'+d+'.start', end_key = 'availability.'+d+'.end'; long t = params.time; if(doc[start_key].size() != 0 && doc[start_key].size() != 0){ for(item in doc['availability.'+d]){ long s =  item['start'].value; long e = item['end'].value; if (t >= s && t < e){ return true; } }}",
            "lang": "painless",
            "params" : {
                "day" : "wed",
                "time" : 300
              }
          }
        }
      }
    }
  }
}

上面的查询返回以下错误

代码语言:javascript
运行
复制
{ ....
"reason": {
          "type": "script_exception",
          "reason": "runtime error",
          "script_stack": [
            "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:94)",
            "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:41)",
            "for(item in doc['availability.'+d]){ long ",
            "                ^---- HERE"
          ],
          "script": "String d = params.day, start_key = 'availability.'+d+'.start', end_key = 'availability.'+d+'.end'; long t = params.time; if(doc[start_key].size() != 0 && doc[start_key].size() != 0){ for(item in doc['availability.'+d]){ long s =  item['start'].value; long e = item['end'].value; if (t >= s && t < e){ return true; } }}",
          "lang": "painless",
          "caused_by": {
            "type": "illegal_argument_exception",
            "reason": "No field found for [availability.wed] in mapping with types []"
          }
        }
..... }

在使用doc['availability']['wed']时也会出现错误

我有什么遗漏的吗?

EN

Stack Overflow用户

回答已采纳

发布于 2019-09-17 18:58:39

如果availability.wed是object类型,请在下面使用

代码语言:javascript
运行
复制
{
  "query": {
    "script": {
      "script": {
        "source": "String d = params.day; for(int i=0; i<doc['availability.'+params.day+'.start'].length;i++){ long start =doc['availability.'+params.day+'.start'][i]; long end = doc['availability.'+params.day+'.end'][i]; if(start <= params.time && end > params.time){ return true;}} ",
        "lang": "painless",
        "params": {
          "day": "wed",
          "time": 2300
        }
      }
    }
  }
}

如果availability.wed的类型为嵌套,请在下面使用

映射:

代码语言:javascript
运行
复制
PUT testindex10/_mappings
{
  "properties": {
    "name":{
      "type": "text"
    },
    "availability": {
      "type": "object",
      "properties": {
        "mon": {
          "type": "nested",
          "properties": {
            "start": {
              "type": "integer"
            }
          }
        },
        "tue": {
          "type": "nested",
          "properties": {
            "start": {
              "type": "integer"
            }
          }
        },
        "wed": {
          "type": "nested",
          "properties": {
            "start": {
              "type": "integer"
            }
          }
        },
        "thu": {
          "type": "nested",
          "properties": {
            "start": {
              "type": "integer"
            }
          }
        },
        "fri": {
          "type": "nested",
          "properties": {
            "start": {
              "type": "integer"
            }
          }
        },
        "sat": {
          "type": "nested",
          "properties": {
            "start": {
              "type": "integer"
            }
          }
        }
      }
    }
  }
}

数据:

代码语言:javascript
运行
复制
[
      {
        "_index" : "testindex10",
        "_type" : "_doc",
        "_id" : "snyiPm0ButCCF6l_WyTl",
        "_score" : 1.0,
        "_source" : {
          "name" : "store1",
          "availability" : {
            "mon" : [
              {
                "start" : 0,
                "end" : 400
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "tue" : [
              {
                "start" : 1300,
                "end" : 2400
              },
              {
                "start" : 0,
                "end" : 400
              }
            ],
            "wed" : [
              {
                "start" : 0,
                "end" : 200
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "thu" : [
              {
                "start" : 1400,
                "end" : 2400
              },
              {
                "start" : 0,
                "end" : 500
              }
            ],
            "fri" : [
              {
                "start" : 0,
                "end" : 400
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ]
          }
        }
      },
      {
        "_index" : "testindex10",
        "_type" : "_doc",
        "_id" : "s3yiPm0ButCCF6l_liQq",
        "_score" : 1.0,
        "_source" : {
          "name" : "store2",
          "availability" : {
            "mon" : [
              {
                "start" : 0,
                "end" : 400
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "tue" : [
              {
                "start" : 1300,
                "end" : 2400
              },
              {
                "start" : 0,
                "end" : 400
              }
            ],
            "wed" : [
              {
                "start" : 0,
                "end" : 500
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "thu" : [
              {
                "start" : 1400,
                "end" : 2400
              },
              {
                "start" : 0,
                "end" : 500
              }
            ],
            "fri" : [
              {
                "start" : 0,
                "end" : 400
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ]
          }
        }
      }
    ]

查询

代码语言:javascript
运行
复制
GET testindex10/_search
{
  "query": {
    "bool": {
      "filter": {
        "nested": {
          "path": "availability.wed",
          "query": {
            "script": {
              "script": {
                "source": "String d = params.day; long start =doc['availability.'+params.day+'.start'].value; long end = doc['availability.'+params.day+'.end'].value; if(start <= params.time && end > params.time){ return true;}  ",
                "lang": "painless",
                "params": {
                  "day": "wed",
                  "time": 400
                }
              }
            }
          }
        }
      }
    }
  }
}

结果:

代码语言:javascript
运行
复制
 [
      {
        "_index" : "testindex10",
        "_type" : "_doc",
        "_id" : "s3yiPm0ButCCF6l_liQq",
        "_score" : 0.0,
        "_source" : {
          "name" : "store2",
          "availability" : {
            "mon" : [
              {
                "start" : 0,
                "end" : 400
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "tue" : [
              {
                "start" : 1300,
                "end" : 2400
              },
              {
                "start" : 0,
                "end" : 400
              }
            ],
            "wed" : [
              {
                "start" : 0,
                "end" : 500
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ],
            "thu" : [
              {
                "start" : 1400,
                "end" : 2400
              },
              {
                "start" : 0,
                "end" : 500
              }
            ],
            "fri" : [
              {
                "start" : 0,
                "end" : 400
              },
              {
                "start" : 1300,
                "end" : 2400
              }
            ]
          }
        }
      }
    ]

解决这个问题的另一种方法是不使用脚本(性能更好)

代码语言:javascript
运行
复制
{
  "query": {
    "bool": {
      "filter": {
        "nested": {
          "path": "availability.wed",
          "query": {
            "bool": {
              "must": [
                {
                  "range": {
                    "availability.wed.start": {
                      "lte": 400
                    }
                  }
                },
                {
                  "range": {
                    "availability.wed.end": {
                      "gte": 400
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}
票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57968917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档