1. Elasticsearch 5.5 入門必會(一)html
2. Elasticsearch 5.5 入門必會之Java client(二)java
咱們先看個簡單的代碼:mysql
@Test public void match() { SearchRequestBuilder requestBuilder = client.prepareSearch("megacorp").setTypes("employee") .setQuery(QueryBuilders.matchQuery("about", "rock climbing")); System.out.println(requestBuilder.toString()); SearchResponse response = requestBuilder.execute().actionGet(); System.out.println(response.status()); if (response.status().getStatus() == 200) { for (SearchHit hits : response.getHits().getHits()) { System.out.println(hits.getSourceAsString()); } } }
===============================================================spring
/** * matchphrase使用,短語精準匹配 */ @Test public void matchPhrase() { SearchRequestBuilder requestBuilder = client.prepareSearch("megacorp").setTypes("employee") .setQuery(QueryBuilders.matchPhraseQuery("about", "rock climbing")); System.out.println(requestBuilder.toString()); SearchResponse response = requestBuilder.execute().actionGet(); System.out.println(response.status()); if (response.status().getStatus() == 200) { for (SearchHit hits : response.getHits().getHits()) { System.out.println(hits.getSourceAsString()); } } }
上面的代碼你能夠理解爲:sql
select * from megacorp_employee where about like '%rock climbing%'
@Test public void aggregation() { SearchRequestBuilder searchBuilder = client.prepareSearch("megacorp").setTypes("employee") .addAggregation(AggregationBuilders.terms("by_interests").field("interests") .subAggregation(AggregationBuilders.terms("by_age").field("age")).size(10)); System.out.println(searchBuilder.toString()); SearchResponse response = searchBuilder.execute().actionGet(); if (response.status().getStatus() == 200) { for (SearchHit hits : response.getHits().getHits()) { System.out.println(hits.getSourceAsString()); } } StringTerms terms = response.getAggregations().get("by_interests"); for (StringTerms.Bucket bucket : terms.getBuckets()) { System.out.println("-interest:" + bucket.getKey() + "," + bucket.getDocCount()); if (bucket.getAggregations() != null && bucket.getAggregations().get("by_age") != null) { LongTerms ageTerms = bucket.getAggregations().get("by_age"); for (LongTerms.Bucket bucket2 : ageTerms.getBuckets()) { System.out.println("--------by age:" + bucket2.getKey() + "," + bucket2.getDocCount()); } } } }
至關於SQL裏面的數據庫
select interests,age,count(1) from megacorp_employee group by interests,age limit 10
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); if(StringUtils.isNotBlank(searchParam.getSearchWords())) { BoolQueryBuilder mutiShould = QueryBuilders.boolQuery(); for(String column : searchType.getSearchColumn()) { mutiShould.should(QueryBuilders.termQuery(column+KEYWORD, searchParam.getSearchWords().trim())); } queryBuilder.must().add(mutiShould); } // 科室編碼過濾 if(StringUtils.isNotBlank(searchParam.getDeptNo())) { queryBuilder.must(QueryBuilders.termQuery("admissward"+KEYWORD, searchParam.getDeptNo().trim())); } /** * 有時間範圍 */ if(searchParam.getTimeType() > 0 && searchParam.getTimeType() < 3) { Date startDate = searchParam.getStartDate(); Date endDate = searchParam.getEndDate(); RangeQueryBuilder rangeBuilder = null; // 入院日期 if(searchParam.getTimeType() == 1) { if(null != startDate) { rangeBuilder = QueryBuilders.rangeQuery("admissdate").gte(startDate.getTime()); } if(null != endDate) { if(null == rangeBuilder) { rangeBuilder = QueryBuilders.rangeQuery("admissdate").lte(endDate.getTime()); } else { rangeBuilder.lte(endDate.getTime()); } } // 出院日期 } else if(searchParam.getTimeType() == 2) { if(null != startDate) { rangeBuilder = QueryBuilders.rangeQuery("disdate").gte(startDate.getTime()); } if(null != endDate) { if(null == rangeBuilder) { rangeBuilder = QueryBuilders.rangeQuery("disdate").lte(endDate.getTime()); } else { rangeBuilder.lte(endDate.getTime()); } } } if(null != rangeBuilder) { queryBuilder.must().add(rangeBuilder); } } SearchRequestBuilder searchBuilder = client.prepareSearch(searchType.getIndexType().get_index()) .setTypes(searchType.getIndexType().get_type()) .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setQuery(queryBuilder) .addSort(StringUtils.isBlank(searchType.getSortColumn())?SCORE:searchType.getSortColumn() , searchType.getOrder()==null?SortOrder.DESC:searchType.getOrder()) .setFrom(pager.getStartRow()).setSize(pager.getPageSize()).setExplain(true); SearchResponse response = searchBuilder.execute().actionGet(); long end = System.currentTimeMillis(); logger.info("searchMutiField request indexType:{},searchparam:{},orderColumn:{},orderBy:{}.total hits:{},cost 【{}】 ms" ,searchType.getIndexType().get_type(),queryBuilder.toString(),searchType.getSearchColumn(), searchType.getOrder(),response.getHits().totalHits,(end-start));
上面的稍微複雜一點,是我生產環境的部分代碼,對應的SQL語句是,其實你看到這一個例子應該就大概知道了怎樣用SQL轉化爲代碼,BoolQueryBuilder.must就至關於SQL裏面的 AND 的概念,Should就是ORexpress
select * from table_name where (column1='searchwords' or column2='searchwords' .. ) and admissward='123456' and admissdate > '1412000212112' and admissdate < '141976521211' limit 10 --個人判斷邏輯是若是是入院日期查詢就 admissdate > startdate and admissdate < endate --若是是出院日期 就disdate > startdate and disdate < enddate --這個邏輯我就不分開寫出來了,省略了
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapping SYSTEM "elastic-config.dtd"> <!-- 屬性參考 https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-store.html --> <mapping > <!-- <datasource id="dataSource1" ref="springDataSource"> </datasource>--> <datasource id="dataSource" > <username>admin</username> <password>admin</password> <jdbcurl>jdbc:mysql://127.0.0.1:3306/message?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=round&useCursorFetch=true&verifyServerCertificate=false&useSSL=false</jdbcurl> <driver>com.mysql.jdbc.Driver</driver> </datasource> <sql-mappings> <sql-mapping data-source-id="dataSource"> <!-- 全量索引 構建 每週星期天3點執行 --> <full-sql> <sql>SELECT * FROM HAHA ORDER BY ID ASC</sql> <expression>0 0 3 ? * SUN</expression> </full-sql> <!-- 每日增量索引構建 --> <incr-sql> <sql>SELECT * FROM HAHA WHERE GMT_CREATE > DATE_ADD(NOW(),INTERVAL -2 DAY) ORDER BY ID ASC</sql> <expression>0 0 2 * * ?</expression> </incr-sql> <search-info> <index>test</index> <type>test</type> <columns> <column index-column="idindex" data-type="integer" sql-column="id" index="not_analyzed" store="no" /> <column index-column="nameindex" data-type="string" sql-column="name" index="not_analyzed" store="no" /> <column index-column="blobtindex" data-type="byte" sql-column="blobt" index="not_analyzed" store="no" /> <column index-column="datesindex" data-type="date" sql-column="ttt" store="no" format="yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" locale="CHINA" /> <column index-column="tinytestindex" data-type="boolean" sql-column="tinytest" index="not_analyzed" store="no" /> <column index-column="moneysindex" data-type="string" sql-column="moneys" index="not_analyzed" store="no" /> <column index-column="ggggindex" data-type="date" sql-column="gggg" format="yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" store="no" /> </columns> </search-info> </sql-mapping> </sql-mappings> </mapping>
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); formatter.setTimeZone(TimeZone.getTimeZone("UTC")); SimpleDateFormat standard = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { return standard.format(formatter.parse(admiss_time)); } catch (ParseException e) { return null; }
//咱們只須要獲取當前咱們本地時間以後getTime傳入便可 admissdate >= xxxxx QueryBuilders.rangeQuery("admissdate").gte(startDate.getTime());
Map<String,Object> map = new HashMap<String,Object>(); map.put("id", 1); //map.put('test',456); map.put("test", 1); //map.put('hehe',567); map.put("hehe", 2); IndexResponse response = client.prepareIndex("emr_document2", "user_info2",map.get('id').toString()) .setSource(map) .get();
我單位乙方提供的數據庫沒有作比較好的分表方案,歷史數據出院一個星期就轉入B表,致使不少系統沒法正常調用出院患者的病歷數據和病人主索引信息,如今已經引入了搜索以後,正常提供所有患者主索引信息查詢服務,用起來很爽!病歷數據+患者主索引數據 總共不超過500W,查詢速度至關快,都在20ms如下!app