Py学习  »  Elasticsearch

ElasticsearchTemplate 使用

常金家的秋意 • 2 年前 • 250 次点击  
阅读 17

ElasticsearchTemplate 使用

一、背景

最近在学习 es 和 java 的整合,整合过程中发现一些查询语句不知道怎么用 java 写,网上也查不到比较全面的,所以就自己整理了下,便于后续查阅。

二、准备环境

2.1 环境信息

框架版本号备注
springboot2.2.6.RELEASE
Elasticsearch7.1.0单机,非集群

2.2 搭建 springboot 环境

maven 配置中需要引入以下 jar 包:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
复制代码

2.3 新增 es 配置文件

/**
 * es 配置文件
 *
 * @author liuqiuyi
 * @date 2021/4/19 23:06
 */
@Configuration
public class TransportClientConfig extends ElasticsearchConfigurationSupport {

	@Bean
	public Client elasticsearchClient() throws UnknownHostException {
		Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
		TransportClient client = new PreBuiltTransportClient(settings);
                // 注意端口为 9300
		client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
		return client;
	}

	@Bean(name = {"elasticsearchOperations", "elasticsearchTemplate"})
	public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException {
		return new ElasticsearchTemplate(elasticsearchClient(), entityMapper());
	}
}
复制代码

三、使用示例

3.1 增、删、改 语句

  • 新建 java bean
/**
 * es 测试对象类
 * @author liuqiuyi
 * @date 2021/4/22 20:38
 */
@Data
@Document(indexName = "employee", type = "_doc")
public class Employee implements Serializable {
	private static final long serialVersionUID = 813700671392848305L;

	private Long id;

	private String name;

	private String job;

	private Integer age;

	private String gender;

	public Employee(Long id, String name, String job, Integer age, String gender) {
		this.id = id;
		this.name = name;
		this.job = job;
		this.age = age;
		this.gender = gender;
	}

	public Employee() {
	}
}
复制代码
  • 新建测试类



    
/**
 * 增 删 改 测试
 *
 * @author liuqiuyi
 * @date 2021/4/28 20:47
 */
public class CrudTest extends UtilsApplicationTests {
	@Resource
	ElasticsearchTemplate elasticsearchTemplate;

	/**
	 * 单个保存 or 更新
	 *
	 * id 不存在,保存
	 * id 已经存在,更新
	 *
	 * @author liuqiuyi
	 * @date 2021/4/28 20:48
	 */
	@Test
	public void saveOrUpdateTest() {
		Employee employee = new Employee(17L, "liuqiuyi", "全栈", 25, "男");

		IndexQuery indexQuery = new IndexQueryBuilder()
				.withObject(employee)
				.build();
		String index = elasticsearchTemplate.index(indexQuery);
		// 返回的 index 是数据 id,如果指定了,返回指定的 id 值,未指定,返回一个 es 自动生成的
		System.out.println(index);
	}


	/**
	 * 批量保存
	 *
	 * @author liuqiuyi
	 * @date 2021/4/29 19:53
	 */
	@Test
	public void batchSaveTest() {
		Employee employeeA = new Employee(18L, "liuqiuyi", "java", 25, "男");
		Employee employeeB = new Employee(19L, "liuqiuyi", "java", 25, "男");
		ArrayList<Employee> employeeArrayList = Lists.newArrayList(employeeA, employeeB);

		List<IndexQuery> indexQueryList = Lists.newArrayList();
		for (Employee employee : employeeArrayList) {
			IndexQuery indexQuery = new IndexQueryBuilder()
					.withObject(employee)
					.build();

			indexQueryList.add(indexQuery);
		}

		elasticsearchTemplate.bulkIndex(indexQueryList);
	}

	/**
	 * 根据 id 单个删除
	 *
	 * @author liuqiuyi
	 * @date 2021/4/29 20:30
	 */
	@Test
	public void deleteByIdTest(){
		String delete = elasticsearchTemplate.delete(Employee.class, "79R2HXkBm5pjjA5okt3o");
		System.out.println(delete);
	}

	/**
	 * 批量删除
	 *
	 * @author liuqiuyi
	 * @date 2021/5/6 15:37
	 */
	@Test
	public void batchDeleteByIdsTest(){
		CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria());
		criteriaQuery.setIds(Lists.newArrayList("18", "19"));

		elasticsearchTemplate.delete(criteriaQuery, Employee.class);
	}
}
复制代码

3.2 简单 DSL 查询

3.2.1 导入测试数据

  • 使用 logstash 导入,具体操作方式见附录

3.2.2 新建 java bean

/**
 * ES 测试对象
 * 需要添加 @Document,指定索引名称和 type(es 7之后是固定值)
 *
 * @author liuqiuyi
 * @date 2021/4/19 23:37
 */
@Data
@Document(indexName = "movies", type = "_doc")
public class Movies implements Serializable {
	private static final long serialVersionUID = -343559824622431609L;

	private String id;
	private String title;
	private String[] genre;
	private Long year;
}
复制代码

3.2.3 查询示例

/**
 * 简单 DSL 查询
 *
 * @author liuqiuyi
 * @date 2021/4/22 20:32
 */
public class SimpleQueryTest extends UtilsApplicationTests {
	@Resource
	ElasticsearchTemplate elasticsearchTemplate;


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "term": {
	 *       "title": {
	 *         "value": "beautiful"
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 16:47
	 */
	@Test
	public void termTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(termQuery("title", "beautiful"))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "terms": {
	 *       "title": [
	 *         "beautiful",
	 *         "mind"
	 *       ]
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 16:53
	 */
	@Test
	public void termsTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(termsQuery("title", "beautiful","mind"))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "range": {
	 *       "year": {
	 *         "gte": 2016,
	 *         "lte": 2018
	 *       }
	 *     }
	 *   },
	 *   "sort": [
	 *     {
	 *       "year": {
	 *         "order": "desc"
	 *       }
	 *     }
	 *   ]
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 16:57
	 */
	@Test
	public void rangeTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(rangeQuery("year").gte(2016).lte(2018))
				.withSort(fieldSort("year").order(SortOrder.DESC))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "constant_score": {
	 *       "filter": {
	 *         "term": {
	 *           "title": "beautiful"
	 *         }
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 17:02
	 */
	@Test
	public void constant_scoreTest()


    
{
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(constantScoreQuery(QueryBuilders.termQuery("title","beautiful")))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "match": {
	 *       "title": "beautiful"
	 *     }
	 *   },
	 *   "from": 10,
	 *   "size": 10
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 17:06
	 */
	@Test
	public void matchTest() {
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(matchQuery("title", "beautiful"))
				// es 的分页,默认是从 0 开始的
				.withPageable(PageRequest.of(1, 10)).build();

		AggregatedPage<Movies> queryForPage = elasticsearchTemplate.queryForPage(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(queryForPage.getContent()));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "_source": [
	 *     "title",
	 *     "id"
	 *   ],
	 *   "query": {
	 *     "match": {
	 *       "title": "beautiful mind"
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 17:13
	 */
	@Test
	public void match_sourceTest() {
		String[] includes = new String[]{"title", "id"};
		FetchSourceFilter sourceFilter = new FetchSourceFilter(includes, null);

		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(matchQuery("title", "beautiful mind"))
				.withSourceFilter(sourceFilter)
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "match_phrase": {
	 *       "title": "beautiful mind"
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 17:20
	 */
	@Test
	public void match_phraseTest() {
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(matchPhraseQuery("title", "beautiful mind"))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "multi_match": {
	 *       "query": "beautiful Adventure",
	 *       "fields": [
	 *         "title",
	 *         "genre"
	 *       ]
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 17:22
	 */
	@Test
	public void multi_matchTest() {
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(multiMatchQuery("beautiful Adventure", "title", "genre"))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "match_all": {}
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 17:26
	 */
	@Test
	public void match_allTest() {
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(matchAllQuery())
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}

	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "query_string": {
	 *       "default_field": "title",
	 *       "query": "mind beautiful",
	 *       "default_operator": "AND"
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 16:16
	 */
	@Test
	public void query_stringTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(queryStringQuery("mind beautiful").defaultField("title").defaultOperator(Operator.AND))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "simple_query_string": {
	 *       "query": "beautiful + mind",
	 *       "fields": [
	 *         "title"
	 *       ]
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/21 17:37
	 */
	@Test
	public void simple_query_stringTest(){
		Map<String, Float> fields = Maps.newHashMap();
		// 不知道这个 value 是什么意思
		fields.put("title", 1f);

		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(simpleQueryStringQuery("mind beautiful").fields(fields).defaultOperator(Operator.AND))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "fuzzy": {
	 *       "title": {
	 *         "value": "neverendign",
	 *         "fuzziness": 1,
	 *         "prefix_length": 5
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * 查询title中从第6个字母开始只要最多纠正一次,就与 neverendign 匹配的所有的数据
	 * es中,是从 0 开始计数的,所以这里是 5
	 * @author liuqiuyi
	 * @date 2021/4/21 17:47
	 */
	@Test
	public void fuzzyTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(fuzzyQuery("title", "neverendign").fuzziness(Fuzziness.ONE).transpositions(true).prefixLength(5))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}



	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "bool": {
	 *       "must": [
	 *         {
	 *           "simple_query_string": {
	 *             "query": "beautiful mind",
	 *             "fields": [
	 *               "title"
	 *             ]
	 *           }
	 *         },
	 *         {
	 *           "range": {
	 *             "year": {
	 *               "gte": 2016,
	 *               "lte": 2018
	 *             }
	 *           }
	 *         }
	 *       ]
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/22 19:19
	 */
	@Test
	public void boolTest(){
		Map<String, Float> fields = Maps.newHashMap();
		// 不知道这个 value 是什么意思


    

		fields.put("title", 1f);

		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(boolQuery().must(simpleQueryStringQuery("beautiful mind").fields(fields)).must(rangeQuery("year").gte(2016).lte(2018)))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}


	/**
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "bool": {
	 *       "filter": [
	 *         {
	 *           "term": {
	 *             "title": "beautiful"
	 *           }
	 *         },
	 *         {
	 *           "range": {
	 *             "year": {
	 *               "gte": 2016,
	 *               "lte": 2018
	 *             }
	 *           }
	 *         }
	 *       ]
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/22 20:00
	 */
	@Test
	public void boolFilterTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(boolQuery().filter(termQuery("title", "beautiful")).must(rangeQuery("year").gte(2016).lte(2018)))
				.build();

		List<Movies> movies = elasticsearchTemplate.queryForList(searchQuery, Movies.class);

		System.out.println(JSON.toJSONString(movies));
	}
}
复制代码

3.3 聚合查询

/**
 *  聚合查询的例子
 *
 * PUT employee/_bulk
 * {"index":{"_id":1}}
 * {"id":1,"name":"Bob","job":"java","age":21,"sal":8000,"gender":"female"}
 * {"index":{"_id":2}}
 * {"id":2,"name":"Rod","job":"html","age":31,"sal":18000,"gender":"female"}
 * {"index":{"_id":3}}
 * {"id":3,"name":"Gaving","job":"java","age":24,"sal":12000,"gender":"male"}
 * {"index":{"_id":4}}
 * {"id":4,"name":"King","job":"dba","age":26,"sal":15000,"gender":"female"}
 * {"index":{"_id":5}}
 * {"id":5,"name":"Jonhson","job":"dba","age":29,"sal":16000,"gender":"male"}
 * {"index":{"_id":6}}
 * {"id":6,"name":"Douge","job":"java","age":41,"sal":20000,"gender":"female"}
 * {"index":{"_id":7}}
 * {"id":7,"name":"cutting","job":"dba","age":27,"sal":7000,"gender":"male"}
 * {"index":{"_id":8}}
 * {"id":8,"name":"Bona","job":"html","age":22,"sal":14000,"gender":"female"}
 * {"index":{"_id":9}}
 * {"id":9,"name":"Shyon","job":"dba","age":20,"sal":19000,"gender":"female"}
 * {"index":{"_id":10}}
 * {"id":10,"name":"James","job":"html","age":18,"sal":22000,"gender":"male"}
 * {"index":{"_id":11}}
 * {"id":11,"name":"Golsling","job":"java","age":32,"sal":23000,"gender":"female"}
 * {"index":{"_id":12}}
 * {"id":12,"name":"Lily","job":"java","age":24,"sal":2000,"gender":"male"}
 * {"index":{"_id":13}}
 * {"id":13,"name":"Jack","job":"html","age":23,"sal":3000,"gender":"female"}
 * {"index":{"_id":14}}
 * {"id":14,"name":"Rose","job":"java","age":36,"sal":6000,"gender":"female"}
 * {"index":{"_id":15}}
 * {"id":15,"name":"Will","job":"dba","age":38,"sal":4500,"gender":"male"}
 * {"index":{"_id":16}}
 * {"id":16,"name":"smith","job":"java","age":32,"sal":23000,"gender":"male"}
 *
 * @author liuqiuyi
 * @date 2021/4/22 20:32
 */
public class AggregationQueryTest extends UtilsApplicationTests {
	@Resource
	ElasticsearchTemplate elasticsearchTemplate;


	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "other_info": {
	 *       "sum": {
	 *         "field": "sal"
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/22 20:41
	 */
	@Test
	public void sumTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(AggregationBuilders.sum("other_info").field("sal"))
				.build();

		Double sumResult = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			// TODO 这里会将具体的数据返回,目前没找到解决办法
			InternalSum internalSum = searchResponse.getAggregations().get("other_info");
			return internalSum.value();
		});

		System.out.println(sumResult);
	}


	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "other_aggs_info": {
	 *       "avg": {
	 *         "field": "sal"
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/23 20:40
	 */
	@Test
	public void avgTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(AggregationBuilders.avg("other_aggs_info").field("sal"))
				.build();

		Double sumResult = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			// TODO 这里会将具体的数据返回,目前没找到解决办法
			InternalAvg avg = searchResponse.getAggregations().get("other_aggs_info");
			return avg.value();
		});

		System.out.println(sumResult);
	}


	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "job_count": {
	 *       "cardinality": {
	 *         "field": "job"
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/23 20:45
	 */
	@Test
	public void cardinalityTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(AggregationBuilders.cardinality("job_count").field("job"))
				.build();

		Double sumResult = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			// TODO 这里会将具体的数据返回,目前没找到解决办法
			InternalCardinality jobCount = searchResponse.getAggregations().get("job_count");
			return jobCount.value();
		});

		System.out.println(sumResult);
	}


	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "max_result": {
	 *       "max": {
	 *         "field": "sal"
	 *       }
	 *     },
	 *     "min_result": {
	 *       "min": {
	 *         "field": "sal"
	 *       }
	 *     },
	 *     "avg_result": {
	 *       "avg": {
	 *         "field": "sal"
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/23 20:48
	 */
	@Test
	public void multivaluedTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(AggregationBuilders.max("max_result").field("sal"))
				.addAggregation(AggregationBuilders.min("min_result").field("sal"))
				.addAggregation(AggregationBuilders.avg("avg_result").field("sal"))
				.build();

		Map<String, Double> resultMap = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			Map<String, Double> stringDoubleMap = Maps.newHashMap();

			InternalMax maxResult = searchResponse.getAggregations().get("max_result");
			InternalMin minResult = searchResponse.getAggregations().get("min_result"


    
);
			InternalAvg avgResult = searchResponse.getAggregations().get("avg_result");

			stringDoubleMap.put("max_result", maxResult.value());
			stringDoubleMap.put("min_result", minResult.value());
			stringDoubleMap.put("avg_result", avgResult.value());
			return stringDoubleMap;
		});

		System.out.println(resultMap);
	}


	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "sal_info": {
	 *       "stats": {
	 *         "field": "sal"
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/25 19:46
	 */
	@Test
	public void statsTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(AggregationBuilders.stats("sal_info").field("sal"))
				.build();

		Map<String, Object> resultMap = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			Map<String, Object> stringDoubleMap = Maps.newHashMap();

			InternalStats stats = searchResponse.getAggregations().get("sal_info");

			stringDoubleMap.put("count", stats.getCount());
			stringDoubleMap.put("min", stats.getMin());
			stringDoubleMap.put("max", stats.getMax());
			stringDoubleMap.put("avg", stats.getAvg());
			stringDoubleMap.put("sum", stats.getSum());

			return stringDoubleMap;
		});

		System.out.println(resultMap);
	}



	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "job_count": {
	 *       "terms": {
	 *         "field": "job"
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/25 20:18
	 */
	@Test
	public void termsTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(AggregationBuilders.terms("job_count").field("job"))
				.build();

		Map<Object, Object> resultMap = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			Map<Object, Object> objectObjectMap = Maps.newHashMap();

			Terms terms = searchResponse.getAggregations().get("job_count");
			for (Terms.Bucket bt : terms.getBuckets()) {
				Object key = bt.getKey();
				long docCount = bt.getDocCount();
				objectObjectMap.put(key, docCount);
			}
			return objectObjectMap;
		});

		System.out.println(resultMap);
	}



	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "job_info": {
	 *       "terms": {
	 *         "field": "job"
	 *       },
	 *       "aggs": {
	 *         "sal_info": {
	 *           "stats": {
	 *             "field": "sal"
	 *           }
	 *         }
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/25 20:36
	 */
	@Test
	public void termsAndStatsTest(){
		TermsAggregationBuilder jobInfoTerm = AggregationBuilders.terms("job_info").field("job");
		StatsAggregationBuilder subTerm = AggregationBuilders.stats("sal_info").field("sal");
		jobInfoTerm.subAggregation(subTerm);

		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(jobInfoTerm)
				.build();

		Map<Object, Object> resultMap = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			Map<Object, Object> objectObjectMap = Maps.newHashMap();

			Terms terms = searchResponse.getAggregations().get("job_info");
			for (Terms.Bucket bt : terms.getBuckets()) {
				Object key = bt.getKey();
				long docCount = bt.getDocCount();
				objectObjectMap.put(key, docCount);
				// 获取子集
				InternalStats aggregations = bt.getAggregations().get("sal_info");
				// 根据需求自行取值
				long count = aggregations.getCount();
			}
			return objectObjectMap;
		});

		System.out.println(resultMap);
	}



	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "job_info": {
	 *       "terms": {
	 *         "field": "job"
	 *       },
	 *       "aggs": {
	 *         "gender_info": {
	 *           "terms": {
	 *             "field": "gender"
	 *           },
	 *           "aggs": {
	 *             "sal_info": {
	 *               "stats": {
	 *                 "field": "sal"
	 *               }
	 *             }
	 *           }
	 *         }
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/25 20:51
	 */
	@Test
	public void multiAggsTest(){
		TermsAggregationBuilder jobInfoTerm = AggregationBuilders.terms("job_info").field("job");
		TermsAggregationBuilder genderInfoTerm = AggregationBuilders.terms("gender_info").field("gender");
		StatsAggregationBuilder subTerm = AggregationBuilders.stats("sal_info").field("sal");

		genderInfoTerm.subAggregation(subTerm);
		jobInfoTerm.subAggregation(genderInfoTerm);

		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(jobInfoTerm)
				.build();

		Map<Object, Object> resultMap = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			Map<Object, Object> objectObjectMap = Maps.newHashMap();

			Terms terms = searchResponse.getAggregations().get("job_info");
			for (Terms.Bucket bt : terms.getBuckets()) {
				Object key = bt.getKey();
				long docCount = bt.getDocCount();
				objectObjectMap.put(key, docCount);
				// 获取子集
				Terms subTerms = bt.getAggregations().get("gender_info");

				for (Terms.Bucket subTermsBucket : subTerms.getBuckets()) {
					Object subKey = subTermsBucket.getKey();
					long subDocCount = subTermsBucket.getDocCount();

					// 获取最里层数据
					InternalStats aggregations = subTermsBucket.getAggregations().get("sal_info");
					// 根据需求自行取值

					// 打印结果,测试用
					System.out.println(subKey + "_" + subDocCount + "_" + JSON.toJSONString(aggregations));
				}
			}
			return objectObjectMap;
		});

		System.out.println(resultMap);
	}



	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "top_age_2": {
	 *       "top_hits": {
	 *         "size": 2,
	 *         "sort": [
	 *           {
	 *             "age": {
	 *               "order": "desc"
	 *             }
	 *           }
	 *         ]
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/26 20:29
	 */
	@Test
	public void TopHitsTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes(


    
"_doc")
				.addAggregation(AggregationBuilders.topHits("top_age_2").size(2))
				.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC))
				.build();


		List<Employee> resultList = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			List<Employee> employeeList = Lists.newArrayList();

			InternalTopHits hits = searchResponse.getAggregations().get("top_age_2");

			SearchHit[] subHits = hits.getHits().getHits();
			for (SearchHit subHit : subHits) {
				// TODO 这里使用了 JSONString to Object
				String sourceAsString = subHit.getSourceAsString();
				Employee employee = JSON.parseObject(sourceAsString, Employee.class);

				employeeList.add(employee);
			}
			return employeeList;
		});

		System.out.println(resultList);
	}



	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "sal_info": {
	 *       "range": {
	 *         "field": "sal",
	 *         "ranges": [
	 *           {
	 *             "key": "0 <= sal <= 5000",
	 *             "from": 0,
	 *             "to": 5000
	 *           },
	 *           {
	 *             "key": "5001 <= sal <= 10000",
	 *             "from": 5001,
	 *             "to": 10000
	 *           },
	 *           {
	 *             "key": "10001 <= sal <= 15000",
	 *             "from": 10001,
	 *             "to": 15000
	 *           }
	 *         ]
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/27 20:00
	 */
	@Test
	public void rangeTest(){
		RangeAggregationBuilder rangeAggregationBuilder = AggregationBuilders.range("sal_info").field("sal")
				.addRange("0 <= sal <= 5000", 0d, 5000d)
				.addRange("5001 <= sal <= 10000", 5001d, 10000d)
				.addRange("10001 <= sal <= 15000", 10001d, 15000d);

		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(rangeAggregationBuilder)
				.build();

		List<Long> resultList = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			List<Long> docCountList = Lists.newArrayList();
			Range range = searchResponse.getAggregations().get("sal_info");
			for (Range.Bucket bucket : range.getBuckets()) {
				long docCount = bucket.getDocCount();
				docCountList.add(docCount);
			}
			return docCountList;
		});
		System.out.println(JSON.toJSONString(resultList));
	}


	/**
	 * GET employee/_search
	 * {
	 *   "size": 0,
	 *   "aggs": {
	 *     "sal_info": {
	 *       "histogram": {
	 *         "field": "sal",
	 *         "interval": 5000,
	 *         "extended_bounds": {
	 *           "min": 0,
	 *           "max": 30000
	 *         }
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/27 20:29
	 */
	@Test
	public void histogramTest(){
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("employee").withTypes("_doc")
				.addAggregation(AggregationBuilders.histogram("sal_info").field("sal").interval(5000d).extendedBounds(0d, 30000d))
				.build();

		List<Long> resultList = elasticsearchTemplate.query(searchQuery, searchResponse -> {
			List<Long> docCountList = Lists.newArrayList();
			Histogram histogram = searchResponse.getAggregations().get("sal_info");
			for (Histogram.Bucket bucket : histogram.getBuckets()) {
				long docCount = bucket.getDocCount();
				docCountList.add(docCount);
			}
			return docCountList;
		});
		System.out.println(JSON.toJSONString(resultList));
	}
}
复制代码

3.4 其它查询

/**
 * 其它查询语句
 *
 * @author liuqiuyi
 * @date 2021/4/28 19:56
 */
public class OtherQueryTest extends UtilsApplicationTests {
	@Resource
	ElasticsearchTemplate elasticsearchTemplate;

	/**
	 * 推荐搜索
	 *
	 * GET movies/_search
	 * {
	 *   "suggest": {
	 *     "title_suggestion": {
	 *       "text": "drema",
	 *       "term": {
	 *         "field": "title",
	 *         "suggest_mode": "popular"
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/27 20:48
	 */
	@Test
	public void recommendationTest(){
		// 构建 推荐搜索 的条件
		TermSuggestionBuilder suggestionBuilder = SuggestBuilders.termSuggestion("title")
				.suggestMode(TermSuggestionBuilder.SuggestMode.POPULAR).text("drema");

		SearchResponse searchResponse = elasticsearchTemplate.suggest(new SuggestBuilder().addSuggestion("title_suggestion", suggestionBuilder), Movies.class);
		// 取值
		TermSuggestion termSuggestion = searchResponse.getSuggest().getSuggestion("title_suggestion");
		TermSuggestion.Entry options = termSuggestion.getEntries().get(0);
		options.forEach(e -> {
			Text text = e.getText();
			float score = e.getScore();
			int freq = e.getFreq();

			System.out.println(text.toString() + "-" + score + "-" + freq);
		});
	}


	/**
	 * 自动补全
	 *
	 * PUT articles
	 * {
	 *   "mappings": {
	 *     "properties": {
	 *       "title_completion":{    // 字段名
	 *         "type": "completion"  // 类型
	 *       }
	 *     }
	 *   }
	 * }
	 * --------------------------
	 * POST articles/_bulk
	 * {"index":{}}
	 * {"title_completion":"liuqiuyi"}
	 * {"index":{}}
	 * {"title_completion":"ls liuqiuyi"}
	 * {"index":{}}
	 * {"title_completion":"this is a liuqiuyi"}
	 * ---------------------------
	 * POST articles/_search
	 * {
	 *   "size": 0,
	 *   "suggest": {
	 *     "articles_suggest": {
	 *       "prefix": "l",
	 *       "completion": {
	 *         "field": "title_completion"
	 *       }
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/28 20:20
	 */
	@Test
	public void automaticCompletionTest(){
		CompletionSuggestionBuilder suggestionBuilder = SuggestBuilders.completionSuggestion("title_completion").prefix("l");

		SearchResponse searchResponse = elasticsearchTemplate.suggest(new SuggestBuilder().addSuggestion("articles_suggest", suggestionBuilder), "articles");

		// 取值
		CompletionSuggestion completionSuggestion = searchResponse.getSuggest().getSuggestion("articles_suggest");
		List<CompletionSuggestion.Entry.Option> options = completionSuggestion.getOptions();
		for (CompletionSuggestion.Entry.Option option : options) {
			SearchHit hit = option.getHit();
			String sourceAsString = hit.getSourceAsString();

			System.out.println(sourceAsString);
		}
	}



	


    
/**
	 * 高亮显示
	 *
	 * GET movies/_search
	 * {
	 *   "query": {
	 *     "match": {
	 *       "title": "beautiful"
	 *     }
	 *   },
	 *   "highlight": {
	 *     "post_tags": "</span>",
	 *     "pre_tags": "<span color='red'>",
	 *     "fields": {
	 *       "title": {}
	 *     }
	 *   }
	 * }
	 *
	 * @author liuqiuyi
	 * @date 2021/4/28 20:22
	 */
	@Test
	public void highlightTest(){
		HighlightBuilder highlightBuilder = new HighlightBuilder().postTags("</span>").preTags("<span color='red'>").field("title");

		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withIndices("movies").withTypes("_doc")
				.withQuery(matchQuery("title", "beautiful"))
				.withHighlightBuilder(highlightBuilder)
				.build();

		elasticsearchTemplate.query(searchQuery, searchResponse -> {
			SearchHits hits = searchResponse.getHits();
			SearchHit[] resultHits = hits.getHits();
			for (SearchHit resultHit : resultHits) {
				Map<String, HighlightField> highlightFields = resultHit.getHighlightFields();
				for (Map.Entry<String, HighlightField> entry : highlightFields.entrySet()) {
					HighlightField value = entry.getValue();
					Text[] fragments = value.getFragments();
					// 根据业务需要自行取值
					System.out.println(entry.getKey() + "-" + fragments[0]);
				}
			}
			return null;
		});
	}
}
复制代码

四、附录

4.1 使用 logstash 导入数据

  • 官网下载 logstash 并解压
  • 在 logstash 的 config 目录下,新建一个 logstash.conf 文件,内容如下:
input {
  file {
    # 数据文件的目录
    path => "/Users/liuqiuyi/Desktop/myWorkSpace/utils/docker/logstash-7.1.0/cvs/movies.csv"
    start_position => "beginning"
    # 监听文件读取的日志记录,如果第一次导入失败,记得删除掉这个日志,在进行第二次导入
    sincedb_path => "/Users/liuqiuyi/Desktop/myWorkSpace/utils/docker/logstash-7.1.0/logs/db_path.log"
  }
}
filter {
  csv {
    separator => ","
    columns => ["id","content","genre"]
  }

  mutate {
    split => { "genre" => "|" }
    remove_field => ["path", "host","@timestamp","message"]
  }

  mutate {

    split => ["content", "("]
    add_field => { "title" => "%{[content][0]}"}
    add_field => { "year" => "%{[content][1]}"}
  }

  mutate {
    convert => {
      "year" => "integer"
    }
    strip => ["title"]
    remove_field => ["path", "host","@timestamp","message","content"]
  }

}
output {
   elasticsearch {
     # 指定 es 地址
     hosts => "http://localhost:9200"
     # 指定索引名
     index => "movies"
     document_id => "%{id}"
   }
  stdout {}
}
复制代码
  • 开始导入,执行以下命令
./bin/logstash -f ./config/logstash.conf
复制代码
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/114013
 
250 次点击