关于"基于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
。