在Java代码中使用刚才建立的索引,并进行查询,删除,添加,修改
- 先说查询吧,DSL语句比较长,慢慢看
首先在项目中使用java建一个关于这个索引的实体类
package com.stock.ir.notify.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.stock.core.annotation.Document;
import com.stock.core.annotation.IndexField;
import com.stock.core.dto.Indexable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
//通报的索引
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
//刚才建索引时候取得别名
@Document(indexName = "notify_management_info")
public class NotifyManagementIndexDto extends Indexable implements Serializable {
//刚才气的字段名字,一定要对应上
@IndexField(name = "document_number_t", description = "文号")
private String documentNumber;
@IndexField(name = "notify_name_t", description = "通报名称")
private String notifyName;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@IndexField(name = "issue_date_dt", description = "发文日期")
private String issueDate;
@IndexField(name = "publish_status_k", description = "发布状态")
private String publishStatus;
@IndexField(name = "business_classification_id_txt", description = "分类id")
private List<String> businessClassificationId;
@IndexField(name = "business_classification_name_t", description = "分类名称")
private String businessClassificationName;
@IndexField(name = "organ_classification_id_txt", description = "分类id")
private List<String> organClassificationId;
@IndexField(name = "organ_classification_name_t", description = "分类名称")
private String organClassificationName;
@IndexField(name = "notify_content_t", description = "通报文件内容")
private String notifyContent;
@IndexField(name = "notify_sortname_t", description = "通报名称排序字段")
private String notifySortName;
@IndexField(name = "publication_all_flag_k", description = "发文范围全员可见")
private String publicationAllFlag;
@IndexField(name = "visible_depts_txt", description = "发文范围按部门")
private List<String> visibleDeptIds;
@IndexField(name = "visible_users_txt", description = "发文范围按人员")
private List<String> visibleUserIds;
@IndexField(name = "visible_roles_txt", description = "发文范围按角色")
private List<String> visibleRoleIds;
@IndexField(name = "visible_groups_txt", description = "发文范围按组")
private List<String> visibleGroupIds;
public void setId(String id) {
this.id = id;
}
}
使用基本查询DSL语句,执行之后控制台输出的语句,这段代码也可以用在elasticSearch中的复合查询中使用。
{
"track_total_hits": true,
"from": 0,
"size": 20,
"_source": [
"id",
"issue_date_dt",
"notify_name_t",
"notify_sortname_t",
"document_number_t",
"publish_status_k",
"business_classification_id_txt",
"business_classification_name_t",
"organ_classification_id_txt",
"organ_classification_name_t",
"notify_content_t",
"visible_depts_txt",
"visible_users_txt",
"visible_roles_txt",
"visible_groups_txt",
"publication_all_flag_k"
],
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"filter":[
{"bool":{
"must":[
{
"match_all":{}
},
{
"term":{
"publish_status_k":{
"value":"1"}
}
},
{
"bool":{
"should":[
{
"term": {
"publication_all_flag_k": {
"value": "1"
}
}
}
,{
"terms": {
"visible_depts_txt": [
"1"
],
"boost": 1
}
}
,{
"terms": {
"visible_users_txt": [
"1"
],
"boost": 1
}
}
,{
"terms": {
"visible_groups_txt": [
"1",
"3F2715F7692547E6B2E90DF817CE8B05"
],
"boost": 1
}
}
,{
"terms": {
"visible_roles_txt": [
"1",
"100450320903048854" ],
"boost": 1
}
}
]
}
}
]
}
}
]
}
},
"aggs": {
"business_classification_id_txt": {
"terms": {
"field": "business_classification_id_txt",
"size": 5000,
"min_doc_count": 0
}
},
"organ_classification_id_txt": {
"terms": {
"field": "organ_classification_id_txt",
"size": 5000,
"min_doc_count": 0
}
}
},
"sort": [
{
"issue_date_dt": {
"order": "asc"
}
}
]
}
java代码中的DSL语句
<?xml version="1.0" encoding="UTF-8"?>
<elasticsearch-dynamic-statement
nameSpace="com.stock.ir.notifyMain.dao.NotifyManagementEs">
<select id="getNotifyManagementList" type="dsl"
resultType="com.stock.ir.notifyMain.dto.NotifyManagementIndexDto">
<![CDATA[
{
"track_total_hits": true,
<#if startRow??>
"from": ${startRow},
</#if>
<#if pageSize??>
"size": ${pageSize},
</#if>
"_source": [
"id",
"issue_date_dt",
"notify_name_t",
"notify_sortname_t",
"document_number_t",
"publish_status_k",
"business_classification_id_txt",
"business_classification_name_t",
"organ_classification_id_txt",
"organ_classification_name_t",
"notify_content_t",
"visible_depts_txt",
"visible_users_txt",
"visible_roles_txt",
"visible_groups_txt",
"publication_all_flag_k"
],
"query": {
"bool": {
"must": [
{
"match_all": {}
}
<#if condition.titleKeyAnd?? && (condition.titleKeyAnd?size > 0)>
,{
"bool": {
"must": [
<#list condition.titleKeyAnd as item>
{
"match_phrase": {
"notify_name_t": {
"query": "${item?j_string}"
}
}
}
<#if item_has_next>,
</#if>
</#list>
]
}
}
</#if>
<#if condition.titleKeyOr?? && (condition.titleKeyOr?size > 0)>
,{
"bool": {
"should": [
<#list condition.titleKeyOr as item>
{
"match_phrase": {
"notify_name_t": {
"query": "${item?j_string}"
}
}
}
<#if item_has_next>,
</#if>
</#list>
]
}
}
</#if>
<#if condition.titleKeyNot?? && (condition.titleKeyNot?size > 0)>
,{
"bool": {
"must_not": [
<#list condition.titleKeyNot as item>
{
"match_phrase": {
"notify_name_t": {
"query": "${item?j_string}"
}
}
}
<#if item_has_next>,
</#if>
</#list>
]
}
}
</#if>
<#if condition.fullKeyAnd?? && (condition.fullKeyAnd?size > 0)>
,{
"bool": {
"must": [
<#list condition.fullKeyAnd as item>
{
"match_phrase": {
"notify_content_t": {
"query": "${item?j_string}"
}
}
}
<#if item_has_next>,
</#if>
</#list>
]
}
}
</#if>
<#if condition.fullKeyOr?? && (condition.fullKeyOr?size > 0)>
,{
"bool": {
"should": [
<#list condition.fullKeyOr as item>
{
"match_phrase": {
"notify_content_t": {
"query": "${item?j_string}"
}
}
}
<#if item_has_next>,
</#if>
</#list>
]
}
}
</#if>
<#if condition.fullKeyNot?? && (condition.fullKeyNot?size > 0)>
,{
"bool": {
"must_not": [
<#list condition.fullKeyNot as item>
{
"match_phrase": {
"notify_content_t": {
"query": "${item?j_string}"
}
}
}
<#if item_has_next>,
</#if>
</#list>
]
}
}
</#if>
<#-- 文号 -->
<#if condition.documentNumber??>
<#assign documentNumberStr = condition.documentNumber?string>
<#if documentNumberStr?length gt 0>
,{
"bool": {
"should": [
{
"wildcard": {
"document_number_t": {
"value": "*${documentNumberStr}*"
}
}
}
]
}
}
</#if>
</#if>
],
"filter":[
{"bool":{
"must":[
{
"match_all":{}
},
{
"term":{
"publish_status_k":{
"value":"1"}
}
},
{
"bool":{
"should":[
{
"term": {
"publication_all_flag_k": {
"value": "${condition.publicationAllFlag}"
}
}
}
<#if condition.visibleDeptIds??&&(condition.visibleDeptIds?size>0)>
,{
"terms": {
"visible_depts_txt": [
<#list condition.visibleDeptIds as item>
<#if !item_has_next>
"${item}"
<#else>
"${item}",
</#if>
</#list>
],
"boost": 1
}
}
</#if>
<#if condition.visibleUserIds??&&(condition.visibleUserIds?size>0)>
,{
"terms": {
"visible_users_txt": [
<#list condition.visibleUserIds as item>
<#if !item_has_next>
"${item}"
<#else>
"${item}",
</#if>
</#list>
],
"boost": 1
}
}</#if>
<#if condition.visibleGroupIds??&&(condition.visibleGroupIds?size>0)>
,{
"terms": {
"visible_groups_txt": [
<#list condition.visibleGroupIds as item>
<#if !item_has_next>
"${item}"
<#else>
"${item}",
</#if>
</#list>
],
"boost": 1
}
}
</#if>
<#if condition.visibleRoleIds??&&(condition.visibleRoleIds?size>0)>
,{
"terms": {
"visible_roles_txt": [
<#list condition.visibleRoleIds as item><#if !item_has_next>"${item}"<#else>"${item}",
</#if></#list>
],
"boost": 1
}
}</#if>
]
}
}
<#if condition.businessClassificationId ?? && (condition.businessClassificationId?size > 0)>
,{
"terms": {
"business_classification_id_txt": [
<#list condition.businessClassificationId as item>
<#if !item_has_next>
"${item}"
<#else>
"${item}",
</#if>
</#list>
],
"boost": 1
}
}
</#if>
<#if condition.organClassificationId ?? && (condition.organClassificationId?size > 0)>
,{
"terms": {
"organ_classification_id_txt": [
<#list condition.organClassificationId as item>
<#if !item_has_next>
"${item}"
<#else>
"${item}",
</#if>
</#list>
],
"boost": 1
}
}
</#if>
<#if condition.notifyIdList?? && (condition.notifyIdList?size > 0)>
,{
"terms": {
"id": [
<#list condition.notifyIdList as item>
"${item}"<#if item_has_next>,</#if>
</#list>
],
"boost": 1
}
}
</#if>
<#-- 发文日期 -->
<#if condition.issueDateStart?? >
,{
"range": {
"issue_date_dt": {
"from": "${condition.issueDateStart}",
"to": "${condition.issueDateEnd}",
"include_lower": true,
"include_upper": true,
"boost": 1
}
}
}
</#if>
]
}
}
]
}
},
"aggs": {
"business_classification_id_txt": {
"terms": {
"field": "business_classification_id_txt",
"size": 5000,
"min_doc_count": 0
}
},
"organ_classification_id_txt": {
"terms": {
"field": "organ_classification_id_txt",
"size": 5000,
"min_doc_count": 0
}
}
},
"sort": [
<#list condition.sortByList as item>
{
"${item.field}": {
"order": "${item.order}"
}
}<#if item_has_next>,</#if>
</#list>
]
}
]]>
</select>
</elasticsearch-dynamic-statement>
- 在这里面传参收参,返回结果从建立的对应索引的实体类返回,传参自己写一个java代码,里面需要什么就写什么。
- <#if startRow??>加if的目的就是判断是否为空,否则执行会报错
- _source:[] 是需要的索引中字段名字,不能有对应不上的名字
- must是必须满足这个条件,should是或者,must_not是不包含
-
<#if condition.fullKeyOr?? && (condition.fullKeyOr?size > 0)>...</#if>
:判断condition.fullKeyOr
数组是否为空,如果不为空,执行if内部的代码。 -
<#list condition.fullKeyOr as item>...</#list>
:遍历condition.fullKeyOr
数组中的元素,并为每个元素生成一个子查询。 -
{ "match_phrase": { "notify_content_t": { "query": "${item?j_string}" } } }
:这是一个match_phrase查询,用于匹配"notify_content_t"
这个字段中是否含有item
字符串。其中使用了${item?j_string}
表达式获取item
的字符串值。 -
<#if item_has_next>, </#if>
:判断是否为最后一个元素,如果不是,就在当前元素和下一个元素之间加入一个逗号 -
<#if condition.documentNumber??>...</#if>
:判断condition.documentNumber
是否存在,如果存在,执行if内部的代码。 -
<#assign documentNumberStr = condition.documentNumber?string>
:获取condition.documentNumber
���字符串值,并赋值给documentNumberStr
。 -
<#if documentNumberStr?length gt 0>...</#if>
:判断documentNumberStr
的长度是否大于0,如果大于0,执行if内部的代码。 -
{ "wildcard": { "document_number_t": { "value": "*${documentNumberStr}*" } } }
:这是一个wildcard查询,用于匹配"document_number_t"
这个字段是否含有特定的字符串,其中特定的字符串是${documentNumberStr}
。 -
<#if condition.issueDateStart?? >...</#if>
:这是一个FTL语言中的条件判断语句,用于判断condition.issueDateStart
是否存在。如果存在,则执行if内部的代码。 -
"range"
:该查询用于匹配一个范围内的值,其中包含多个子查询,这里只有一个子查询。 -
"issue_date_dt"
:该子查询用于匹配"issue_date_dt"
字段。 -
"from"
:该子查询用于指定匹配范围的下限,这里使用${condition.issueDateStart}
作为下限值,${...}
表示FTL语言中的表达式。 -
"to"
:该子查询用于指定匹配范围的上限,这里使用${condition.issueDateEnd}
作为上限值,${...}
表示FTL语言中的表达式。 -
"include_lower"
和"include_upper"
:这两个子查询用于指定下限和上限是否包含,如果包含,则值为true
,否则为false
。 -
"boost"
:该子查询指定了查询的权重值,可以根据实际情况调整。 -
aggs
:该参数用于执行聚合查询,其中包含了多个聚合子查询。 -
"business_classification_id_txt"
和"organ_classification_id_txt"
:这两个子查询分别用于对"business_classification_id_txt"
和"organ_classification_id_txt"
这两个字段进行聚合查询。 -
"terms"
:该子查询用于计算某个字段中的不同值的出现次数。 -
"field"
:该子查询指定了需要计算的字段。 -
"size"
:该子查询指定了需要计算的文档数量上限,超过这个上限的文档将被忽略。 -
"min_doc_count"
:该子查询指定了需要计算的文档数量下限,如果某个值的出现次数小于该下限,则不会被计算在内。 -
sort
:该参数用于对查询结果进行排序,其中包含多个排序条件。 -
<#list condition.sortByList as item>...</#list>
:这是一个FTL语言中的列表循环语句,用于将输入参数中的排序字段和排序方式加入到查询中。 -
${item.field}
:这是FTL语言中的字符串变量,表示当前循环到的排序字段。
在service中将传的参数写入,判断时间等
HashMap<String, Object> resultMap = new HashMap<>();
NotifyManagementEsDto esParam = new NotifyManagementEsDto();
esParam.setPublishStatus("1");
esParam.setBusinessClassificationId(getBusinessChildrenClassIdList(notifyManagementMainEsDto.getBusinessClassificationId()));
esParam.setOrganClassificationId(getOrganChildrenClassIdList(notifyManagementMainEsDto.getOrganClassificationId()));
esParam.setTitleKeyAnd(formatKeyWord(notifyManagementMainEsDto.getTitleKeyAnd())); // 标题包含以下全部关键词
esParam.setTitleKeyOr(formatKeyWord(notifyManagementMainEsDto.getTitleKeyOr())); // 标题包含以下任一关键词
esParam.setTitleKeyNot(formatKeyWord(notifyManagementMainEsDto.getTitleKeyNot())); // 标题不包含以下关键词
esParam.setFullKeyAnd(formatKeyWord(notifyManagementMainEsDto.getFullKeyAnd())); // 全文包含以下全部关键词
esParam.setFullKeyOr(formatKeyWord(notifyManagementMainEsDto.getFullKeyOr())); // 全文包含以下任一关键词
esParam.setFullKeyNot(formatKeyWord(notifyManagementMainEsDto.getFullKeyNot())); // 全文不包含以下关键词
if (StringUtils.isNotEmpty(notifyManagementMainEsDto.getIssueDateStart())) {
esParam.setIssueDateStart(notifyManagementMainEsDto.getIssueDateStart());
}
if (StringUtils.isNotEmpty(notifyManagementMainEsDto.getIssueDateEnd())) {
esParam.setIssueDateEnd(notifyManagementMainEsDto.getIssueDateEnd());
}
if(CollectionUtils.isNotEmpty(notifyManagementMainEsDto.getNotifyIdList())){
esParam.setNotifyIdList(notifyManagementMainEsDto.getNotifyIdList());
}
esParam.setDocumentNumber(notifyManagementMainEsDto.getDocumentNumber());
esParam.setPublicationAllFlag("1");
其中getBusinessChildrenClassIdList,getOrganChildrenClassIdList是用来查询分类的方法,这是单独的方法,不和上面的查询写在一起。
private ArrayList<String> getBusinessChildrenClassIdList(String businessclassificationId) {
if (StringUtils.isBlank(businessclassificationId)) {
return new ArrayList<>();
}
//通过NotifyBusinessClassificationExample创建一个空的业务类别查询对象example,
//并使用notifyBusinessClassificationMapper查询出所有已经存在的业务类别对象列表
//保存到List对象classificationList中。
NotifyBusinessClassificationExample example = new NotifyBusinessClassificationExample();
List<NotifyBusinessClassification> classificationList = notifyBusinessClassificationMapper.selectByExample(example);
//创建一个新的ArrayList对象childrenList,并将传入的业务分类ID添加到childrenList对象中。
ArrayList<String> childrenList = new ArrayList<>();
childrenList.add(businessclassificationId);
//遍历classificationList对象,对每个业务类别对象进行以下操作:
//a) 判断当前业务类别是否为传入的业务分类ID的直接子类别,如果不是直接跳过。
//b) 如果当前业务类别是传入的业务分类ID的直接子类别,则取出这个业务类别的ID添加到childrenList对象中。
//c) 针对当前业务类别的每个子业务类别,重复进行a)~b)的操作。
//d) 最后返回完整的业务类别ID链表对象childrenList。
for (NotifyBusinessClassification notifyBusinessClassification : classificationList) {
if (!businessclassificationId.equals(notifyBusinessClassification.getParentId())) {
continue;
}
String childId = notifyBusinessClassification.getId();
childrenList.add(childId);
for (NotifyBusinessClassification notifyBusinessClassification1 : classificationList) {
if (!childId.equals(notifyBusinessClassification1.getParentId())) {
continue;
}
String childId1 = notifyBusinessClassification1.getId();
childrenList.add(childId1);
for (NotifyBusinessClassification notifyBusinessClassification2 : classificationList) {
if (!childId1.equals(notifyBusinessClassification2.getParentId())) {
continue;
}
String childId2 = notifyBusinessClassification2.getId();
childrenList.add(childId2);
for (NotifyBusinessClassification notifyBusinessClassification3 : classificationList) {
if (!childId2.equals(notifyBusinessClassification3.getParentId())) {
continue;
}
String childId3 = notifyBusinessClassification3.getId();
childrenList.add(childId3);
}
}
}
}
return childrenList;
}
因为需求需要,使用排序将查询出来的数据进行排序
Map<String, String> sortBy = notifyManagementMainEsDto.getSortBy();
if (sortBy.size() > 0) { // 非空验证
String[] valueArr = sortBy.get("value").split(",");
String[] methodArr = sortBy.get("method").split(",");
List<Map<String, String>> orderList = new ArrayList<>();
for (int i = 0; i < valueArr.length; i++) {
HashMap<String, String> sort = new HashMap<>();
sort.put("field", valueArr[i]);
sort.put("order", "des".equals(methodArr[i]) ? "desc" : methodArr[i]); // 前端排序组件只能传”des“
orderList.add(sort);
}
esParam.setSortByList(orderList);
}
创建QueryInfo对象,设置查询起始行,页大小,查询条件和查询Id,setQueryId就是写的dsl语句所在的类的路径,
- //调用searchClient对象的searchWithFacet方法进行带聚合(Facet)的ES检索,传入了分隔符(NOTIFY_MANAGEMENT_SPLIT) //QueryInfo对象和结果映射类(NotifyManagementIndexDto.class)作为参数。
//创建了一个QueryInfo对象,并设置了查询的起始行、页大小、查询条件和查询ID,其中查询条件是由参数esParam对象提供的。
QueryInfo<NotifyManagementEsDto> queryInfo = new QueryInfo<>();
queryInfo.setStartRow(Integer.parseInt(notifyManagementMainEsDto.getStart()));
queryInfo.setPageSize(Integer.parseInt(notifyManagementMainEsDto.getPageSize()));
queryInfo.setCondition(esParam);
//调用searchClient对象的searchWithFacet方法进行带聚合(Facet)的ES检索,传入了分隔符(NOTIFY_MANAGEMENT_SPLIT)、
//QueryInfo对象和结果映射类(NotifyManagementIndexDto.class)作为参数。
queryInfo.setQueryId("com.stock.ir.notifyMain.dao.NotifyManagementEs.getNotifyManagementList");
FacetResult<NotifyManagementIndexDto> indexDtoFacetResult = searchClient.searchWithFacet(NOTIFY_MANAGEMENT_SPLIT, queryInfo, NotifyManagementIndexDto.class);
List<NotifyManagementIndexDto> notifyManagementIndexDtos = indexDtoFacetResult.getPage().getData();
int total = indexDtoFacetResult.getPage().getTotal();
//查询目录树条数,从indexDtoFacetResult对象中的statisticsFieldMap映射中取出key为business_classification_id_txt的List对象,并将其赋值给businessClassificationCount变量。
List<StatisticsField> businessClassificationCount = indexDtoFacetResult.getStatisticsFieldMap().get("business_classification_id_txt");
List<StatisticsField> organClassificationCount = indexDtoFacetResult.getStatisticsFieldMap().get("organ_classification_id_txt");
resultMap.put("notifyManagementIndexDtos", notifyManagementIndexDtos);//基本信息
resultMap.put("businessClassificationCount", businessClassificationCount);
resultMap.put("organClassificationCount", organClassificationCount);
resultMap.put("total", total); // 查询总条数
return resultMap;
//查询目录树条数,从indexDtoFacetResult对象中的statisticsFieldMap映射中取出key为business_classification_id_txt的List对象,并将其赋值给businessClassificationCount变量。
List<StatisticsField> businessClassificationCount = indexDtoFacetResult.getStatisticsFieldMap().get("business_classification_id_txt");
List<StatisticsField> organClassificationCount = indexDtoFacetResult.getStatisticsFieldMap().get("organ_classification_id_txt");