四、倒排索引
倒排索引是由单词词典、倒排列表两部分组成,单词词典记录的所有文档的单词,记录单词倒排列表的关联关系
倒排列表记录了单词对应的文档结合,由倒排索引项组成,分别为文档ID、词频TF、位置、偏移
案例:
ElasticSearch可以为json文档中的每个字段设置自己的倒排索引,也可以指定某些字段不做倒排索引
若不做倒排索引,虽可以节省存储空间,但字段无法被搜索
五、使用Analyzer进行分词
首先你得知道什么是分词:Analysis把全文本转换为一系列单词的过程叫做分词
Analysis通过Analyzer实现的,可以通过ElasticSearch内置的分析器、或使用定制分析器
分词器除了写入时转换此条,查询query时也需要用相同的分析器对查询语句进行分析
案例:ElasticSearch kaka
通过分词就转化为 elasticSearch和kaka,这里需要注意的是通过分词转化后把单词的首字母变为小写
Analyzer的组成
Character Fiters :针对原始文本处理,例如去除html
Tokenizer : 按照规则切分单词
Token Filter : 将切分的单词进行加工,转为小写,删除stopwords并增加同义词
ElasticSearch的内置分词器
# Standard Analyzer - 默认分词器,按词切分,小写处理 # 只做单词分割、并且把单词转为小写 get _analyze { "analyzer":"standard", "text":"If you don't expect quick success, you'll get a pawn every day" } # Simple Analyzer - 按照非字母切分(符号被过滤),小写处理 # 按照非字母切分例如字母与字母之间的——,非字母的都被去除例如下边的 2 get _analyze { "analyzer" :"simple", "text":"3 If you don't expect quick success, you'll get a pawn every day kaka-niuniu" } # Whitespace Analyzer - 按照空格切分,不转小写 # 仅仅是根据空格切分,再无其它 get _analyze { "analyzer":"whitespace", "text":"3 If you don't expect quick success, you'll get a pawn every day" } # Stop Analyzer - 小写处理,停用词过滤(the,a, is) # 按照非字母切分例如字母与字母之间的——,非字母的都被去除例如下边的 2 # 相比Simple Analyze,会把the,a,is等修饰性词语去除 get _analyze { "analyzer":"stop", "text":"4 If you don't expect quick success, you'll get a pawn every day" } # Keyword Analyzer - 不分词,直接将输入当作输出 # 不做任何分词,直接把输入的输出,假如你不想使用任何分词时就可以使用这个 get _analyze { "analyzer":"keyword", "text":"5 If you don't expect quick success, you'll get a pawn every day" } # Patter Analyzer - 正则表达式,默认\W+(非字符分隔) # 通过正则表达式进行分词,默认是\W+,非字符的符号进行分割 get _analyze { "analyzer":"pattern", "text":"6 If you don't expect quick success, you'll get a pawn every day" } # Language 一提供了30多种常见语言的分词器 # 通过不同语言进行分词 # 会把复数转为单数 ,会把单词的ing去除 get _analyze { "analyzer":"english", "text":"7 If you don't expect quick success, you'll get a pawn every day kakaing kakas" } # 中文分词器 # 这个需要安装 # 执行: ./bin/elasticsearch-plugin install analysis-icu # 重启:nohup ./bin/elasticsearch > /dev/null 2>&1 & get _analyze { "analyzer":"icu_analyzer", "text":"你好,我是咔咔" }
其它中文分词
用的最多的IK分词,只是自定义词库,支持热更新分词字典
清华大学自然语言一套分词器Thulac
六、Search Api
通过Url query 实现搜索
例如:
get /movies/_search?q=2012&df=title&sort=year:desc
q:指定查询语句,使用Query String Syntax
df:查询字段,不指定时,会对所有字段进行查询
sort:排序、from和size用于分页
Profile:可以查看查询是如果被执行的
指定字段查询、泛查询
指定字段查询就是加上df即可、泛查询什么都不加,看案例
通过下图右侧信息可得知,指定字段查询的是title中存在2012的数据
同样也可以这样来写指定字段查询
get /movies/_search?q=2012&df=title { "profile":true }
通过下图右侧可得知,泛查询则是在所有字段中查找存在2012的数
分组与引号查询
若你查询值为Beautiful Mind 则等效于Beautiful OR Mind ,类似于MySQL中的or语句,意思为查询的字段中包含 Beautiful 或者 Mind 都会被查询出来
若你查询值为"Beautiful Mind" 则等效于Beautiful AND Mind ,类似于MySQL中的and语句,意思为查询的字段中不仅要包含Beautiful 而且还需要包含 Mind ,跟MySQL中不同的是顺序也不能变
注意:这里你乍一眼看过去没啥区别, 其实区别就在于有无引号
# PhraseQuery # 需要字段title中存在beautiful 和 mind,并且两者的顺序不能乱 # "description" : """title:"beautiful mind"""" get /movies/_search?q=title:"Beautiful Mind" { "profile":"true" } # TermQuery # 需要字段title中出现beautiful 或 mind 都可以 # "type" : "BooleanQuery", # "description" : "title:beautiful title:mind", get /movies/_search?q=title:(Beautiful Mind) { "profile":"true" }
布尔操作
可以使用AND / OR / NOT 或者 && / || / ! 这里你会发现使用的都是大写,+表示must(必须存在),-表示not mast(必须不存在)接下来看案例
# title 里边必须有beautiful 和 mind # "description" : "+title:beautiful +title:mind" get /movies/_search?q=title:(Beautiful AND Mind) { "profile":"true" } # title里边包含beautiful 必须没有mind # "description" : "title:beautiful -title:mind" get /movies/_search?q=title:(Beautiful NOT Mind) { "profile":"true" } # title里包含beautiful ,必须也包含mind # "description" : "title:beautiful +title:mind" get /movies/_search?q=title:(Beautiful %2BMind) { "profile":"true" }
范围查询、通配符查询、模糊匹配
# year年份大于1996的电影 # 注意一下[] 为闭区间 {}为开区间 # "description" : "year:[1997 TO 9223372036854775807]" get /movies/_search?q=year:>1996 { "profile":"true" } # title 中存在b的数据 # "description" : "title:b*" get /movies/_search?q=title:b* { "profile":"true" } # 对于模糊匹配还是非常有必要的,因为会存在一起用户会输错单词,我们就可以给做近似度匹配 # "description" : "(title:beautiful)^0.875" get /movies/_search?q=title:beautifl~1 { "profile":"true" }