ElaticSearch使用term filter来搜索数据
1.插入测试数据
1.1 回忆批量操作_bulk
语法
{action:{metadata}}\n
{request body}\n
{action:{metadata}}\n
{request body}\n
.....
action行为 | 解释 |
---|---|
create | 当文档不存在时进行创建 |
index | 创建新文档或替换已有文档 |
update | 局部更新文档 |
delete | 删除一个文档 |
例如:
{"delete":{"_index":"library","_type":"books","_id":"1"}}
其他action的演示
1.2 插入测试数据
POST /forum/article/_bulk
{ "index": { "_id": 1 }}
{ "articleID" : "XHDK-A-1293-#fJ3", "userID" : 1, "hidden": false, "postDate": "2017-01-01" }
{ "index": { "_id": 2 }}
{ "articleID" : "KDKE-B-9947-#kL5", "userID" : 1, "hidden": false, "postDate": "2017-01-02" }
{ "index": { "_id": 3 }}
{ "articleID" : "JODL-X-1937-#pV7", "userID" : 2, "hidden": false, "postDate": "2017-01-01" }
{ "index": { "_id": 4 }}
{ "articleID" : "QQPX-R-3956-#aD8", "userID" : 2, "hidden": true, "postDate": "2017-01-02" }
注意:最后一行也要进行换行,不然会报错
初步来说,就先搞4个字段,因为整个es是支持json document格式的,所以说扩展性和灵活性非常之好。如果后续随着业务需求的增加,要在document中增加更多的field,那么我们可以很方便的随时添加field。
2.根据用户ID搜索帖子
GET /forum/article/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"userID" : 1
}
}
}
}
}
- term:对搜索文本不分词,直接拿去倒排索引中匹配,你输入的是什么,就去匹配什么
例如:“hello world” --> “hello world”,直接去倒排索引中匹配“hello world”
注意点:所以就会产生一个问题,比如我们在demo(索引)下新增这4个文档
当我们使用term去搜索"spotless future"时无法搜索到结果
原因在于:分词器将"spotless future"分析成"spotless"和"future"作为关键词,生成到倒排索引的检索目录中
GET /demo/_analyze
{
"field": "text",
"text": "Whatever your past has been, you have a spotless future"
}
通过term,将"spotless future"作为一个关键词去倒排索引中匹配,当然是无法匹配的
替代的查询方法:match_phrase
3.搜索没有隐藏的帖子
GET /forum/article/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"hidden" : false
}
}
}
}
}
4.根据发帖日期搜索帖子
GET /forum/article/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"postDate" : "2017-01-01"
}
}
}
}
}
5.根据帖子ID搜索帖子
GET /forum/article/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"articleID" : "XHDK-A-1293-#fJ3"
}
}
}
}
}
搜索结果为空,为什么查不到呢?
- articleID.keyword,是es最新版本内置建立的field,就是不分词的。
- 所以一个articleID过来的时候,会建立两次索引,一次是自己本身,是要分词的,分词后放入倒排索引;
- 另外一次是基于articleID.keyword,不分词,保留256个字符最多,直接一个字符串放入倒排索引中
- 所以term filter,对text过滤,可以考虑使用内置的field.keyword来进行匹配。
- 但是有个问题,默认就保留256个字符。所以尽可能还是自己去手动建立索引,指定not_analyzed吧。在最新版本的es中,不需要指定not_analyzed也可以,将type=keyword即可。
使用field.keyword进行匹配
GET /forum/article/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"articleID.keyword" : "XHDK-A-1293-#fJ3"
}
}
}
}
}
扩展:
当我们插入的数据是text类型时,例如插入"articleID":“XHDK-A-1293-#fJ3”,在mappings中,除了原本的articleID字段,在articleID字段下还有一个keyword字段
- articleID的type表示自己本身,是要分词的,分词后放入倒排索引
- articleID.keyword的type是不分词的,直接将字符串放入倒排索引中
验证articleID的分词
GET /forum/_analyze
{
"field": "articleID",
"text": "XHDK-A-1293-#fJ3"
}
分词器将 "XHDK-A-1293-#fJ3"分成"xhdk","a","1293","fj3"放入倒排索引中(字段为articleID)
验证articleID.keyword的分词
GET /forum/_analyze
{
"field": "articleID.keyword",
"text": "XHDK-A-1293-#fJ3"
}
直接将"XHDK-A-1293-#fJ3"扔到倒排索引中(字段为articleID.keyword)
6.查看分词
GET /forum/_analyze
{
"field": "articleID",
"text": "XHDK-A-1293-#fJ3"
}
- 默认是analyzed的text类型的field,建立倒排索引的时候,就会对所有的articleID分词,分词以后,原本的articleID就没有了,只有分词后的各个word存在于倒排索引中。
- term,是不对搜索文本分词的,XHDK-A-1293-#fJ3 --> XHDK-A-1293-#fJ3;但是articleID建立索引的时候,XHDK-A-1293-#fJ3 --> xhdk,a,1293,fj3
7.重建索引
DELETE /forum
PUT /forum
{
"mappings": {
"article": {
"properties": {
"articleID": {
"type": "keyword"
}
}
}
}
}
POST /forum/article/_bulk
{ "index": { "_id": 1 }}
{ "articleID" : "XHDK-A-1293-#fJ3", "userID" : 1, "hidden": false, "postDate": "2017-01-01" }
{ "index": { "_id": 2 }}
{ "articleID" : "KDKE-B-9947-#kL5", "userID" : 1, "hidden": false, "postDate": "2017-01-02" }
{ "index": { "_id": 3 }}
{ "articleID" : "JODL-X-1937-#pV7", "userID" : 2, "hidden": false, "postDate": "2017-01-01" }
{ "index": { "_id": 4 }}
{ "articleID" : "QQPX-R-3956-#aD8", "userID" : 2, "hidden": true, "postDate": "2017-01-02" }
当articleID的类型指定为keyword,就不会进行分词了
8.重新根据帖子ID和发帖日期进行搜索
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"articleID" : "XHDK-A-1293-#fJ3"
}
}
}
}
}
总结:
- term filter:根据exact value进行搜索,数字、boolean、date天然支持
- text需要建索引时指定为not_analyzed,才能用term query
- 相当于SQL中的单个where条件
select *
from forum.article
where articleID='XHDK-A-1293-#fJ3'