关于"基于Java操作",我们主要讨论如何基于Java建立连接,以及如何查询等。
至于如何建立索引等,我们不会讨论。因为一般在企业中,不会用Java去建索引,导数据等。
连接
建立连接查看索引
我们直接看建立连接的代码。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 35 |
解释说明:
TransportClient,基于TCP连接,利用9300端口。有且仅有一个实现类PreBuiltTransportClient。PreBuiltTransportClient的Settings是客户端的配置,如果采取默认设置,可以填入Settings.EMPTY。
对于集群,一般需要填写的集群名称,如果集群名称不对,连接不上。
可以通过.put("client.transport.ignore_cluster_name", true),忽略集群名字验证。transportClient.addTransportAddress(transportAddress);,为添加节点地址。transportClient.admin().indices().prepareGetIndex().execute().actionGet(),获取index数组。
查看索引mapping
通过如下的代码可以查看索引的mapping。
1 | transportClient.admin().indices().getMappings(new GetMappingsRequest().indices(indice)).get() |
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | type = doc |
MatchAllQuery
查询所有,基于MatchAllQueryBuilder。
示例代码:
1 | package com.kakawanyifan; |
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:1967937 |
解释说明:
prepareSearch():传入index,可变参数。setTypes():传入type,可变参数。
那么,为什么我们要通过getHits().getTotalHits())获取总数,通过getHits().getMaxScore())获取最大得分,通过getHits().getHits()获取结果数组呢?
联系我们在上一张的讨论。
示例代码:
1 | GET /ems/_doc/_search |
运行结果:
1 | { |
一样的结构
From-Size-Sort
分页查询基于三个方法:
setFrom()setSize()addSort()
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:1967937 |
解释说明:
setFrom(起始条数):起始条数setSize(每页条数):每页条数addSort(排序字段,排序方式):排序SortOrder.DESC:降序SortOrder.ASC:升序
- 因为我们指定了排序方式,干预了ES的默认排序方式,所以最大得分为
NaN。
TermQuery
关键词查询基于TermQueryBuilder。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:12 |
再来一个,我们查entfullname是上汽通用五菱汽车股份有限公司的数据。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:0 |
没有?
这不奇怪,因为我们的entfullname是text类型的,被分词了。
1 | { |
我们发现,这个entfullname内部还有一个keyword类的。
来,我们把QueryBuilders.termQuery("entfullname", "上汽通用五菱汽车股份有限公司");中的entfullname,改成entfullname.keyword。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:292 |
MatchPhraseQuery
或者利用MatchPhraseQueryBuilder,其首先将查询字符串解析成一个词项列表,然后对这些词项进行搜索,但只保留那些包含全部搜索词项,且位置与搜索词项相同的文档。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:298 |
TermsQuery
TermsQuery,类似于SQL中的in。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | {"eid":"q4dfba4f9b2df43838fe2752e16784931","create_time":"2022/01/16 17:15:25","entfullname":"上海汽车集团股份有限公司","channel":"","modify_type":"I","source":"wx","groupname":"微信","irhkeybbsnum":"d3f08a909e7bc473","update_time":"2022/01/16 17:15:25","pubtime":"2022/01/16 16:29:31","dwh_created_time":"2022-01-17 22:10:31.520690000"} |
RangeQuery
范围查询基于RangeQueryBuilder及其四个相关方法:
lt:小于lte:小于等于gt:大于gte:大于等于
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:1967937 |
解释说明:
- 对于时间,需要利用
format("yyyy-MM-dd"),转换成相同格式才能比较。
WildcardQuery
通配符查询,基于WildcardQueryBuilder及其两个符号。
*:所有?:一个
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:0 |
查不到?也是因为被分词了。
PrefixQuery
PrefixQuery,查找含有指定前缀的关键词的相关文档。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:97062 |
BoolQuery
布尔查询基于BoolQueryBuilder及其四个方法:
must():必须匹配must查询条件should():应该匹配should查询中的一个或多个must_not():必须不匹配
must有点类似and,should有点类似or。但只是有点类似,区别我们在上一章《2.基本操作》有过讨论。
通过上述方法,我们可以匹配任何方法。
例如。我们查询
entfullname是上汽通用五菱汽车股份有限公司或比亚迪股份有限公司或北京汽车集团有限公司或上海汽车集团股份有限公司- 且
infoEmotion是正面 - 且
infocategory1是经营管理且infocategory2是战略布局且infocategory3是战略合作- 或
infocategory1是经营管理且infocategory2是企业项目且infocategory3是公司项目
- 且
groupname是国内新闻 - 且
pubtime大于等于2022-01-01 - 且
pubtime小于等于2022-01-02 - 另外,
pubtime从近到远,每页10条的第2页
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:389 |
特别的,将鼠标移动到boolQueryBuilder,可以看到其查询用的JSON脚本。
FetchSource
返回指定字段基于setFetchSource()方法,第一个参数为包含哪些字段,第二个参数为排除哪些字段。例如
setFetchSource("*","age"),返回所有字段,但排除age字段。setFetchSource("name",""),只返回name字段。setFetchSource(new String[]{},new String[]{}),分别指定字段。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | 总记录数:1967937 |
Scroll
那么,如果我们想获取全量数据怎么办?
setFrom(0) setSize(Integer.MaxValue)?
不,一般默认from+size不能超过一万。
设置太大的话,会有性能问题。
可以考虑Scroll,滚动搜索。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 |
|
Highlight
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | irauthors |
MultiMatchQuery
MultiMatchQuery,一个查询关键词,和多个字段进行匹配。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | {"create_time":"2022/01/02 23:20:25","channel":"微博","modify_type":"I","trsabstract":"始终都要开始新的生活呀 临沂·临沂上海路万达广场 http://t.cn/AiEZnMdz","urlcontent":"5aeL57uI6YO96KaB5byA5aeL5paw55qE55Sf5rS75ZGAIOS4tOaygsK35Li05rKC5LiK5rW36Lev\r\n5LiH6L6+5bm/5Zy6IGh0dHA6Ly90LmNuL0FpRVpuTWR6","source":"wb","title":"","groupname":"微博","content":"始终都要开始新的生活呀 临沂·临沂上海路万达广场 http://t.cn/AiEZnMdz","url":"http://weibo.com/6359885207/L8WSmivji","savetime":"2022/01/02 23:20:25","irhkeybbsnum":"4721329464410264","irauthors":"香菜给你吃x","update_time":"2022/01/02 23:20:25","irsrcname":"","pubtime":"2022/01/02 23:08:44","sitename":"新浪","trskeyworks":"临沂;上海路;万达;新的;广场;http;都要;AiEZnMdz;始终","dwh_created_time":"2022-01-04 14:43:27.304132000","urldate":"2022/01/02 00:00:00"} |
FuzzyQuery
FuzzyQuery,模糊查询。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | {"eid":"q646973a7e3b22b5f56f426c3ca70b843","create_time":"2022/01/18 13:18:23","entfullname":"比亚迪股份有限公司","channel":"推荐","modify_type":"I","source":"news","groupname":"国内新闻","irhkeybbsnum":"55630549005802140670","update_time":"2022/01/18 13:18:23","pubtime":"2022/01/17 10:21:51","credit_code":"91440300192317458F","dwh_created_time":"2022-01-18 22:42:01.658617000"} |
Collapse
根据指定的字段,进行折叠。类似于SQL中的distinct。
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | {"irhkeybbsnum":"4727140559358332","pubtime":"2022/01/18 23:59:58"} |
查询方法很多,我们不可能穷尽所有的查询方法,还有多字段分词查询(QueryStringQuery)、ids查询(IdsQuery)等,很多方法,我们没有讨论。
Filter
示例代码:
1 | package com.kakawanyifan; |
运行结果:
1 | {"sufpoint":"[{\"index\":\"57\",\"word\":\"合作\"}]","pnum":"23","create_time":"2022/01/02 22:42:28","infoemtionlabel":"正面","entfullname":"中国航空工业集团有限公司","channel":"合肥","range":"31","modify_type":"I","source":"news","prepoint":"[{\"index\":\"26\",\"word\":\"中国航空工业集团\"}]","groupname":"国内新闻","irhkeybbsnum":"60582722411432775190","update_time":"2022/01/02 22:42:28","pubtime":"2022/01/02 22:26:26","infocategory2":"战略布局","infocategory3":"战略合作","dwh_created_time":"2022-01-04 14:43:04.190296000","infocategory1":"经营管理"} |
个人疑惑,根据各种资料
Filter都是在Query之前的,所以我比较疑惑的是为什么方法名是.setPostFilter,而不是.setPreFilter。