我必须在Elasticsearch中构造一个非常重要的查询(现在看来是这样)。假设我有两个实体,每个实体都有一个数组元素,由字符串组成:
1). ['A', 'B']
2). ['A', 'C']
3). ['A', 'E']
4). ['A']
数组元素的映射如下(使用动态模板):
{
"my_array_of_strings": {
"path_match": "stringArray*",
"mapping": {
"type": "string",
"index": "not_analyzed"
}
}
}
实体的Json表示如下:
{
"stringArray": [
"A",
"B"
]
}
然后我有了用户输入:['A','B','C']。
我想要实现的是找到只包含输入中指定元素的实体——预期结果是:[A'、[B']、[A'、[C']、[A'],但不是['A'、[E'](因为用户输入中不存在“E”)。
这个场景可以用Elasticsearch实现吗?
更新:除了使用脚本的解决方案之外——脚本应该可以很好地工作,但很可能会在有许多记录匹配的情况下大大降低查询速度——我还设计了另一个脚本。下面,我将尝试解释它的主要思想,而不是代码实现。
我没有提到的一个重要条件(这可能会给其他用户提供有价值的提示)是数组由枚举元素组成,即数组中此类元素的数量有限。这允许将此类数组展平为实体的单独字段。
假设有5个可能的值:“A”、“B”、“C”、“D”、“E”。这些值中的每一个都是一个布尔字段——如果它为空(即数组版本将包含此元素)则为true,否则为false。然后每个实体都可以重写如下:
1).
A = true
B = true
C = false
D = false
E = false
2).
A = true
B = false
C = true
D = false
E = false
3).
A = true
B = false
C = false
D = false
E = true
4).
A = true
B = false
C = false
D = false
E = false
当用户输入['A','B','C']时,我需要做的就是:A)取所有可能的值(['A','B','C','D','E']),并从中减去用户输入-
这将如预期的那样给出记录1、2和4。我仍在试验这种方法的代码实现,但到目前为止,它看起来很有希望。它还需要测试,但我认为这可能比在查询中使用脚本执行得更快,对资源的要求也更低。
为了进一步优化这一点,可能根本不提供“false”字段,并将之前的查询修改为“D=不存在和E=不存在”-结果应该是相同的。
在同样的情况下,我做了以下步骤:
首先,我删除了索引,用sense plugin
重新定义analyzer/settings
。
DELETE my_index
然后我为my_index定义了自定义分析器
PUT my_index
{
"index" : {
"analysis" : {
"tokenizer" : {
"comma" : {
"type" : "pattern",
"pattern" : ","
}
},
"analyzer" : {
"comma" : {
"type" : "custom",
"tokenizer" : "comma"
}
}
}
}
}
然后,我在代码中定义了映射属性,但您也可以使用sense来实现这一点。他们两个都一样。
PUT /my_index/_mapping/my_type
{
"properties" : {
"conduct_days" : {
"type" : "string",
"analyzer" : "comma"
}
}
}
然后进行以下测试步骤:
PUT /my_index/my_type/1
{
"coduct_days" : "1,2,3"
}
PUT /my_index/my_type/2
{
"conduct_days" : "3,4"
}
PUT /my_index/my_type/3
{
"conduct_days" : "1,6"
}
GET /my_index/_search
{
"query": {"match_all": {}}
}
GET /my_index/_search
{
"filter": {
"or" : [
{
"term": {
"coduct_days": "6"
}
},
{
"term": {
"coduct_days": "3"
}
}
]
}
}
您可以通过脚本实现这一点,这就是它的外观
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"terms": {
"name": [
"A",
"B",
"C"
]
}
},
{
"script": {
"script": "if(user_input.containsAll(doc['name'].values)){return true;}",
"params": {
"user_input": [
"A",
"B",
"C"
]
}
}
}
]
}
}
}
}
}
这个groovy脚本
正在检查列表是否包含除['A',B',C']
之外的任何内容,如果包含,则返回false,因此它不会返回['A',E']
。它只是检查子列表是否匹配。这个脚本可能需要几秒钟。您需要启用动态脚本
,而且ES 2的语法可能不同。x
,如果不起作用,请告诉我。
编辑1
我只把这两个条件都放在过滤器
中。首先只返回包含A、B或C的文档,然后脚本只应用于这些文档,所以这将比前一个更快。更多关于过滤器排序的信息
希望这有帮助!!
问题内容: 假设我有以下代码: 我可以手动调用下一个函数多次,以使2个数组按“相同名称”分组。 问题是我不知道变量值,在这种情况下为“ dinner”和“ lunch”,因此我想按名称自动对这个statEvents数组进行分组,所以当名称不同时,我会得到尽可能多的数组。 我该怎么办? 问题答案: 从Swift 4开始,此功能已添加到标准库中。您可以这样使用它: 斯威夫特3: 不幸的是,上面的函数复
问题内容: 我想做一个相当复杂的查询/聚合。我看不到该怎么做,因为我刚刚开始使用ES。我的文档看起来像这样: 现在,我想为每个关键字计算property_1可以具有的几个可能值中有多少个。也就是说,我需要一个具有以下响应的存储桶聚合: 如果需要映射,您还可以指定哪个吗?我没有任何非默认映射,我只是将所有内容都转储在那里。 编辑:通过在此处发布上一个示例的批量PUT为您节省了麻烦 编辑2: 我只是试
我试图检索一个带有特定'_ID'的文档和一个带有另一个特定'_ID'的嵌入文档。 我的文档是一个目录,它包含一个课程数组。 示例数据: 在mongod中,我运行这个聚合查询,并得到我想要的结果: 正如我前面提到的,我已经得到了一个目录实例,里面有一个课程实例。
我面临的问题是,我有两个文档,每个文档都包含一个对象数组。我喜欢搜索一个包含嵌套对象两个属性的文档(在同一对象中同时匹配这两个属性),但我总是同时得到这两个文档。 我用以下内容创建了文档: 我为它们定义了一个索引,以防止ES像这样平整对象: 现在,我想使用以下查询搜索第一个文档(): 这应该只返回一个同时匹配两个条件的元素。 不幸的是,它总是返回两个文档。我想这是因为在某个时候,ES仍然会将嵌套对
问题内容: 给定n个元素的数组,即 我可以编写一个扩展,以便可以修改数组以实现以下输出: 有没有一种方法可以实现将数组移动任何索引(正数或负数)的功能。我可以使用子句以命令式方式实现此功能,但我正在寻找的是功能性实现。 该算法很简单: 通过提供的索引将数组分为两个 将第一个数组附加到第二个数组的末尾 有什么方法可以以功能样式实现它吗? 我完成的代码: 问题答案: 您可以使用远程下标并连接结果。这将
我只想在数组中的第一个元素上搜索对象,而忽略其余的元素。例如,对于下面的数据,如果我只想在中搜索数组中的第一个元素。 我知道我可以这样做一个嵌套查询,但这里的问题是所有的车辆都被搜索。我只希望车辆列表中的第0个元素被搜索,其余的被忽略。 理想情况下,我需要类似这样的东西来每次搜索列表中的第一辆车。有什么方法可以有效地做到这一点吗?