首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >弹性搜索多个字段多参数搜索

弹性搜索多个字段多参数搜索
EN

Stack Overflow用户
提问于 2020-04-15 02:21:15
回答 1查看 86关注 0票数 1

我只想返回此课程,如果‘等级’= 'G6‘和类型=’开放‘在同一受众标签中匹配,它们必须存在于同一标签中才能返回此课程。目前,如果该课程发现G6和开放的受众不同,则会返回该课程,这不是我想要的。这是不正确的,我得到了不正确的数据,我需要查询以应用于每个受众,只有在同一受众为真时才返回数据

下面是我的json:

代码语言:javascript
复制
{
"took": 1,
"timed_out": false,
"_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
},
"hits": {
    "total": 71,
    "max_score": 3.3118114,
    "hits": [
        {
            "_index": "courses",
            "_type": "course",
            "_id": "LBTBWdzyRw-jgiiYssjv8A",
            "_score": 3.3118114,
            "_source": {
                "id": "LBTBWdzyRw-jgiiYssjv8A",
                "title": "1503 regression testing",
                "shortDescription": "asdf",
                "description": "asdf",
                "learningOutcomes": "",
                "modules": [],
                "learningProvider": {
                    "id": "ig2-zIY_QkSpMC4O0Lm0hw",
                    "name": null,
                    "termsAndConditions": [],
                    "cancellationPolicies": []
                },
                "audiences": [
                    {
                        "id": "VfDpsS_5SXi8iZubzTkUBQ",
                        "name": "comm",
                        "areasOfWork": [
                            "Communications"
                        ],
                        "departments": [],
                        "grades": [
                            "G6"
                        ],
                        "interests": [],
                        "requiredBy": null,
                        "frequency": null,
                        "type": "OPEN",
                        "eventId": null
                    },
                    {
                        "id": "eZPPPqTqRdiDAE3xCPlJMQ",
                        "name": "analysis",
                        "areasOfWork": [
                            "Analysis"
                        ],
                        "departments": [],
                        "grades": [
                            "G6"
                        ],
                        "interests": [],
                        "requiredBy": null,
                        "frequency": null,
                        "type": "REQUIRED",
                        "eventId": null
                    }
                ],
                "preparation": "",
                "owner": {
                    "scope": "LOCAL",
                    "organisationalUnit": "co",
                    "profession": 63,
                    "supplier": ""
                },
                "visibility": "PUBLIC",
                "status": "Published",
                "topicId": ""
            }
        }
    ]
}

}

我的ES代码:

代码语言:javascript
复制
 BoolQueryBuilder boolQuery = boolQuery();

    boolQuery.should(QueryBuilders.matchQuery("audiences.departments.keyword", department));
    boolQuery.should(QueryBuilders.matchQuery("audiences.areasOfWork.keyword", areaOfWork));
    boolQuery.should(QueryBuilders.matchQuery("audiences.interests.keyword", interest));

    BoolQueryBuilder filterQuery = boolQuery();
    filterQuery.must(QueryBuilders.matchQuery("audiences.grades.keyword", "G6"));
    filterQuery.must(QueryBuilders.matchQuery("audiences.type", "OPEN"));

下面是索引映射:

代码语言:javascript
复制
{
  "media": {
    "aliases": {}
  },
  "courses": {
    "aliases": {}
  },
  "feedback": {
    "aliases": {}
  },
  "learning-providers": {
    "aliases": {}
  },
  "resources": {
    "aliases": {}
  },
  "courses-0.4.0": {
    "aliases": {}
  },
  ".security-6": {
    "aliases": {
      ".security": {}
    }
  },
  "payments": {
    "aliases": {}
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-17 11:02:26

因为您需要query to apply in each audience and only return data if it is true in the same audience,所以您需要为audiences字段指定嵌套数据类型,否则ElasticSearch会以对象的形式存储它,并且它没有嵌套对象的概念,因为Elasticsearch会将对象层次结构展平到一个简单的字段名列表中,而values.You可以参考此来获取更详细的https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html

以您的示例为例,假设这是您的文档:

代码语言:javascript
复制
    "audiences": [
            {
                "id": "1",
                "field": "comm"
            },
           {
                "id": "2",
                "field": "arts"
           }
   ]

Elasticsearch以以下形式展平:

代码语言:javascript
复制
{
   "audiences.id":[1,2],
   "audiences.field":[comm,arts]
}

现在,如果您的搜索查询表明受众必须是id:1和field:arts,那么上面的文档也将匹配。

因此,为了避免这种情况,应该将这种类型的对象定义为nested对象。ElasticSearch将单独存储每个对象,而不是将其展平,因此每个对象都将被单独搜索。

上述文档的映射应为:

映射

代码语言:javascript
复制
{
    "mappings": {
        "properties": {
            "shortDescription": {
                "type": "text"
            },
            "audiences": {
                "type": "nested"
            },
            "description": {
                "type": "text"
            },
            "modules": {
                "type": "text"
            },
            "preparation": {
                "type": "text"
            },
            "owner": {
                "properties": {
                    "scope": {
                        "type": "text"
                    },
                    "organisationalUnit": {
                        "type": "text"
                    },
                    "profession": {
                        "type": "text"
                    },
                    "supplier": {
                        "type": "text"
                    }
                }
            },
            "learningProvider": {
                "properties": {
                    "id": {
                        "type": "text"
                    },
                    "name": {
                        "type": "text"
                    },
                    "termsAndConditions": {
                        "type": "text"
                    },
                    "cancellationPolicies": {
                        "type": "text"
                    }
                }
            },
            "visibility": {
                "type": "text"
            },
            "status": {
                "type": "text"
            },
            "topicId": {
                "type": "text"
            }
        }
    }
}

现在,如果我们为这个文档建立索引:

文档

代码语言:javascript
复制
{
    "shortDescription": "asdf",
    "description": "asdf",
    "learningOutcomes": "",
    "modules": [],
    "learningProvider": {
        "id": "ig2-zIY_QkSpMC4O0Lm0hw",
        "name": null,
        "termsAndConditions": [],
        "cancellationPolicies": []
    },
    "audiences": [
        {
            "id": "VfDpsS_5SXi8iZubzTkUBQ",
            "name": "comm",
            "areasOfWork": [
                "Communications"
            ],
            "departments": [],
            "grades": [
                "G6"
            ],
            "interests": [],
            "requiredBy": null,
            "frequency": null,
            "type": "OPEN",
            "eventId": null
        },
        {
            "id": "eZPPPqTqRdiDAE3xCPlJMQ",
            "name": "analysis",
            "areasOfWork": [
                "Analysis"
            ],
            "departments": [],
            "grades": [
                "G7"
            ],
            "interests": [],
            "requiredBy": null,
            "frequency": null,
            "type": "REQUIRED",
            "eventId": null
        }
    ],
    "preparation": "",
    "owner": {
        "scope": "LOCAL",
        "organisationalUnit": "co",
        "profession": 63,
        "supplier": ""
    },
    "visibility": "PUBLIC",
    "status": "Published",
    "topicId": ""
}

如果搜索查询是这样的:

搜索查询1

代码语言:javascript
复制
{
"query": {
    "nested": {
        "path": "audiences",
        
        "query": {
            "bool": {
                "must": [
                    {
                        "match": {
                            "audiences.type.keyword": "OPEN"
                        }
                        
                    },
                     {
                        "match": {
                            "audiences.grades.keyword": "G6"
                        }
                        
                    }
                ]
            }
        }
       
    }
}

}

结果

代码语言:javascript
复制
"hits": [
        {
            "_index": "product",
            "_type": "_doc",
            "_id": "1",
            "_score": 0.9343092,
            "_source": {
                "shortDescription": "asdf",
                "description": "asdf",
                "learningOutcomes": "",
                "modules": [],
                "learningProvider": {
                    "id": "ig2-zIY_QkSpMC4O0Lm0hw",
                    "name": null,
                    "termsAndConditions": [],
                    "cancellationPolicies": []
                },
                "audiences": [
                    {
                        "id": "VfDpsS_5SXi8iZubzTkUBQ",
                        "name": "comm",
                        "areasOfWork": [
                            "Communications"
                        ],
                        "departments": [],
                        "grades": [
                            "G6"
                        ],
                        "interests": [],
                        "requiredBy": null,
                        "frequency": null,
                        "type": "OPEN",
                        "eventId": null
                    },
                    {
                        "id": "eZPPPqTqRdiDAE3xCPlJMQ",
                        "name": "analysis",
                        "areasOfWork": [
                            "Analysis"
                        ],
                        "departments": [],
                        "grades": [
                            "G7"
                        ],
                        "interests": [],
                        "requiredBy": null,
                        "frequency": null,
                        "type": "REQUIRED",
                        "eventId": null
                    }
                ],
                "preparation": "",
                "owner": {
                    "scope": "LOCAL",
                    "organisationalUnit": "co",
                    "profession": 63,
                    "supplier": ""
                },
                "visibility": "PUBLIC",
                "status": "Published",
                "topicId": ""
            }
        }
    ]

但是现在,如果您的搜索查询是:

搜索查询2:

代码语言:javascript
复制
{
    "query": {
        "nested": {
            "path": "audiences",
            
            "query": {
                "bool": {
                    "must": [
                        {
                            "match": {
                                "audiences.type.keyword": "OPEN"
                            }
                            
                        },
                         {
                            "match": {
                                "audiences.grades.keyword": "G7"
                            }
                            
                        }
                    ]
                }
            }
           
        }
    }
}

结果:

代码语言:javascript
复制
"hits": {
        "total": {
            "value": 0,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
}

因此,简而言之,您需要在映射和rest查询中更改audiences字段的数据类型,以便它可以搜索嵌套数据类型。

因此,不使用下面的代码片段:

代码语言:javascript
复制
BoolQueryBuilder filterQuery = boolQuery();
filterQuery.must(QueryBuilders.matchQuery("audiences.grades.keyword", "G6"));
filterQuery.must(QueryBuilders.matchQuery("audiences.type", "OPEN"));

您应该使用此嵌套查询:

代码语言:javascript
复制
BoolQueryBuilder filterQuery = new BoolQueryBuilder();
filterQuery.must(QueryBuilders.matchQuery("audiences.grades.keyword", "G6"));
filterQuery.must(QueryBuilders.matchQuery("audiences.type", "OPEN"));
NestedQueryBuilder nested = new NestedQueryBuilder("audiences", filterQuery, ScoreMode.None);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61214550

复制
相关文章

相似问题

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