ElasticSearch 从指定术语中查找具有不同嵌套列表元素的索引对象
ElasticSearch find indexed objects with distinct nested list elements from specified terms
假设我们有一个 student 有一个 scores 的(nested)列表如下:
public class Student
{
public string FullName { get; set; }
public List<Score> Scores { get; set; } = new List<int>();
}
public class Score
{
public int Value { get; set; }
}
如何使用 NEST(或简单查询)编写 ElasticSearch 查询来获取至少有 2 个不同分数的所有学生从 7 到 10。
因此,例如,如果学生的分数为 {2,7,10} 或 {8,10},他应该在我们的结果中,而学生的分数为 {10, 6, 5} 或 {8, 8} 或 {2, 7} 不应该出现在我们的结果中。
我想出的是:
GET /index/student/_search
{
"query": {
"nested": {
"path": "scores",
"query": {
"bool": {
"should":
[
{
"bool": {
"filter": [
{
"terms": {
"scores.value": [7, 10]
}
},
{
"terms":{
"scores.value": [8, 9]
}
}
]
}
},
{
"bool": {
"filter": [
{
"terms": {
"scores.value": [7, 8]
}
},
{
"terms":{
"scores.value": [9, 10]
}
}
]
}
}
]
}
}
}
}
}
但 ElasticSearch 似乎不允许 TERMS 查询的连词(返回 0 次匹配)。即使它确实有效,我仍然需要更优雅的东西,因为如果我们有超过 4 个允许值,这将变得很痛苦。
更新
我尝试了以下脚本,但也得到了 0 个结果:
GET /index/student/_search
{
"query": {
"nested": {
"path": "scores",
"query": {
"bool": {
"filter": [
{
"exists": {
"field": "scores"
}
},
{
"script": {
"script": """
boolean condition = false;
def availableScores = [7, 8, 9, 10];
def scores = doc['scores.id'].values;
for (int i = 0; i < scores.length; i++)
for(int j = 0; j < availableScores.length; j++)
if (scores[i] == availableScores[j])
{
if (condition == true)
return (true);
condition = true;
availableScores.remove(j);
break;
}
return (false)"""
}
}
]
}
}
}
}
}
很长一段时间后,我找到了一个有效的查询:
GET /index/student/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"nested": {
"path": "scores",
"query": {
"terms": {
"scores.value": [
7,
10
]
}
}
}
},
{
"nested": {
"path": "scores",
"query": {
"terms": {
"scores.value": [
8,
9
]
}
}
}
}
]
}
},
{
"bool": {
"must": [
{
"nested": {
"path": "scores",
"query": {
"terms": {
"scores.value": [
7,
9
]
}
}
}
},
{
"nested": {
"path": "scores",
"query": {
"terms": {
"scores.value": [
8,
10
]
}
}
}
}
]
}
}
]
}
}
}
这里的技巧是将 1 个嵌套查询分成多个,然后将 它们 放在 should
查询中。
我仍然想要一个更优雅的解决方案(我想是 script
),但现在,我将它作为最终答案。
假设我们有一个 student 有一个 scores 的(nested)列表如下:
public class Student
{
public string FullName { get; set; }
public List<Score> Scores { get; set; } = new List<int>();
}
public class Score
{
public int Value { get; set; }
}
如何使用 NEST(或简单查询)编写 ElasticSearch 查询来获取至少有 2 个不同分数的所有学生从 7 到 10。
因此,例如,如果学生的分数为 {2,7,10} 或 {8,10},他应该在我们的结果中,而学生的分数为 {10, 6, 5} 或 {8, 8} 或 {2, 7} 不应该出现在我们的结果中。
我想出的是:
GET /index/student/_search
{
"query": {
"nested": {
"path": "scores",
"query": {
"bool": {
"should":
[
{
"bool": {
"filter": [
{
"terms": {
"scores.value": [7, 10]
}
},
{
"terms":{
"scores.value": [8, 9]
}
}
]
}
},
{
"bool": {
"filter": [
{
"terms": {
"scores.value": [7, 8]
}
},
{
"terms":{
"scores.value": [9, 10]
}
}
]
}
}
]
}
}
}
}
}
但 ElasticSearch 似乎不允许 TERMS 查询的连词(返回 0 次匹配)。即使它确实有效,我仍然需要更优雅的东西,因为如果我们有超过 4 个允许值,这将变得很痛苦。
更新
我尝试了以下脚本,但也得到了 0 个结果:
GET /index/student/_search
{
"query": {
"nested": {
"path": "scores",
"query": {
"bool": {
"filter": [
{
"exists": {
"field": "scores"
}
},
{
"script": {
"script": """
boolean condition = false;
def availableScores = [7, 8, 9, 10];
def scores = doc['scores.id'].values;
for (int i = 0; i < scores.length; i++)
for(int j = 0; j < availableScores.length; j++)
if (scores[i] == availableScores[j])
{
if (condition == true)
return (true);
condition = true;
availableScores.remove(j);
break;
}
return (false)"""
}
}
]
}
}
}
}
}
很长一段时间后,我找到了一个有效的查询:
GET /index/student/_search
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"nested": {
"path": "scores",
"query": {
"terms": {
"scores.value": [
7,
10
]
}
}
}
},
{
"nested": {
"path": "scores",
"query": {
"terms": {
"scores.value": [
8,
9
]
}
}
}
}
]
}
},
{
"bool": {
"must": [
{
"nested": {
"path": "scores",
"query": {
"terms": {
"scores.value": [
7,
9
]
}
}
}
},
{
"nested": {
"path": "scores",
"query": {
"terms": {
"scores.value": [
8,
10
]
}
}
}
}
]
}
}
]
}
}
}
这里的技巧是将 1 个嵌套查询分成多个,然后将 它们 放在 should
查询中。
我仍然想要一个更优雅的解决方案(我想是 script
),但现在,我将它作为最终答案。