官方网站: https://www.elastic.co/
下载地址: https://www.elastic.co/cn/start
Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库(框架),但是想要使用Lucene,必须使用Java来作为开发语言并将其直接集成到你的应用中,并且Lucene的配置及使用非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
Lucene缺点:
ES vs Solr 检索速度
当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。
大型互联网公司,实际生产环境测试,将搜索引擎从Solr转到 Elasticsearch以后的平均查询速度有了50倍的提升。
总结:
二者安装都很简单。
倒排索引总结:
索引就类似于目录,平时我们使用的都是索引,都是通过主键定位到某条数据,那么倒排索引呢,刚好相反,数据对应到主键.这里以一个博客文章的内容为例:
1.索引:
2.倒排索引
假如,我们有一个站内搜索的功能,通过某个关键词来搜索相关的文章,那么这个关键词可能出现在标题中,也可能出现在文章内容中,那我们将会在创建或修改文章的时候,建立一个关键词与文章的对应关系表,这种,我们可以称之为倒排索引,因此倒排索引,也可称之为反向索引.如:
修改elasticsearch.yml (使用es安装的用户)
mkdir ‐p /usr/local/es/elasticsearch‐7.6.1/log
mkdir ‐p /usr/local/es/elasticsearch‐7.6.1/data
cd /usr/local/es/elasticsearch‐7.6.1/config
vim elasticsearch.yml
cluster.name: my‐application
node.name: node‐1
path.data: /usr/local/es/elasticsearch‐7.6.1/data
path.logs: /usr/local/es/elasticsearch‐7.6.1/log
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["服务器IP"]
cluster.initial_master_nodes: ["node‐1"]
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
http.cors.enabled: true
http.cors.allow‐origin: "*"
修改jvm.option配置文件,调整jvm堆内存大小
cd /usr/local/es/elasticsearch‐7.6.1/config
vi jvm.options
‐Xms2g
‐Xmx2g
由于现在使用普通用户来安装es服务,且es服务对服务器的资源要求比较多,包括内存大小,线程数等。所以我们需要给普通用户解开资源的束缚
普通用户打开文件的最大数限制
ES因为需要大量的创建索引文件,需要大量的打开系统的文件,所以我们需要解除linux系统当中打开文件最大数目的限制,不然ES启动就会抛错
sudo vi /etc/security/limits.conf
* soft nofile 65536
* hard nofile 131072
* soft nproc 4096
* hard nproc 4096
普通用户启动线程数限制
max number of threads [1024] for user [es] likely too low, increase to
at least [4096]原因:无法创建本地线程问题,用户最大可创建线程数太小
解决方案:修改90-nproc.conf 配置文件。
Centos6
sudo vi /etc/security/limits.d/90‐nproc.conf
Centos7
sudo vi /etc/security/limits.d/20‐nproc.conf
* soft nproc 1024#修改为
* soft nproc 4096
普通用户调大虚拟内存
max virtual memory areas vm.max_map_count [65530] likely too low,increase to at least [262144]
调大系统的虚拟内存
原因:最大虚拟内存太小
vi /etc/sysctl.conf,追加以下内容:
vm.max_map_count=655360
保存后,执行:sysctl ‐p
我们后续也需要使用Elasticsearch来进行中文分词,所以需要单独给Elasticsearch安装IK分词器插件。以下为具体安装步骤:
https://github.com/medcl/elasticsearch-analysis-ik/releases
mkdir ‐p /usr/local/es/elasticsearch‐7.6.1/plugins/ik
cd /usr/local/es/elasticsearch‐7.6.1/plugins/ik
解压 elasticsearch‐analysis‐ik‐7.6.1.zip
修改默认分词方法:ik_max_word):
PUT /indexname
{
"settings" : {
"index" : {
"analysis.analyzer.default.type": "ik_max_word"
}
}
}
查询当前类型中的所有文档 _search
格式: GET /索引名称/类型/_search
举例: GET /es_db/_doc/_search
SQL: select * from student
条件查询, 如要查询age等于28岁的 _search?q=:**
格式: GET /索引名称/类型/_search?q=*:***
举例: GET /es_db/_doc/_search?q=age:28
SQL: select * from student where age = 28
范围查询, 如要查询age在25至26岁之间的 _search?q=*[ TO **] 注意:TO 必须为大写
格式: GET /索引名称/类型/_search?q=***[25 TO 26]
举例: GET /es_db/_doc/_search?q=age[25 TO 26]
SQL: select * from student where age between 25 and 26
根据多个ID进行批量查询 _mget
格式: GET /索引名称/类型/_mget
举例: GET /es_db/_doc/_mget
{
"ids":["1","2"]
}
SQL: select * from student where id in (1,2)
查询年龄小于等于28岁的 :<=
格式: GET /索引名称/类型/_search?q=age:<=**
举例: GET /es_db/_doc/_search?q=age:<=28
SQL: select * from student where age <= 28
查询年龄大于28前的 :>
格式: GET /索引名称/类型/_search?q=age:>**
举例: GET /es_db/_doc/_search?q=age:>28
SQL: select * from student where age > 28
分页查询 from=&size=
格式: GET /索引名称/类型/_search?q=age[25 TO 26]&from=0&size=1
举例: GET /es_db/_doc/_search?q=age[25 TO 26]&from=0&size=1
SQL: select * from student where age between 25 and 26 limit 0, 1
对查询结果只输出某些字段 _source=字段,字段
格式: GET /索引名称/类型/_search?_source=字段,字段
举例: GET /es_db/_doc/_search?_source=name,age
SQL: select name,age from student
对查询结果排序 sort=字段:desc/asc
格式: GET /索引名称/类型/_search?sort=字段 desc
举例: GET /es_db/_doc/_search?sort=age:desc
SQL: select * from student order by age desc
Query方式查询,会在ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。
1、根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会采用精确匹配
注意: 采用term精确查询, 查询字段映射类型属于为keyword.
POST /es_db/_doc/_search
{
"query": {
"term": {
"name": "admin"
}
}
}
SQL: select * from student where name = 'admin'
2、根据备注信息模糊查询 match, match会根据该字段的分词器,进行分词查询
POST /es_db/_doc/_search
{
"from": 0,
"size": 2,
"query": {
"match": {
"address": "广州"
}
}
}
SQL: select * from user where address like '%广州%' limit 0, 2
3、多字段模糊匹配查询与精准查询 multi_match
POST /es_db/_doc/_search
{
"query":{
"multi_match":{
"query":"张三",
"fields":["address","name"]
}
}
}
SQL: select * from student where name like '%张三%' or address like '%张三%'
4、范围查询
POST /es_db/_doc/_search
{
"query" : {
"range" : {
"age" : {
"gte":25,
"lte":28
}
}
}
}
SQL: select * from user where age between 25 and 28
5、分页、输出字段、排序综合查询
POST /es_db/_doc/_search
{
"query" : {
"range" : {
"age" : {
"gte":25,
"lte":28
}
}
},
"from": 0,
"size": 2,
"_source": ["name", "age", "book"],
"sort": {"age":"desc"}
}
Filter过滤器方式查询,它的查询不会计算相关性分值,也不会对结果进行排序, 因此效率会高一点,查询的结果可以被缓存。
Filter Context 对数据进行过滤
POST /es_db/_doc/_search
{
"query" : {
"bool" : {
"filter" : {
"term":{
"age":25
}
}
}
}
}
ES中映射可以分为动态映射和静态映射
在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类型、长度、主键等,最后才能基于表插入数据。而Elasticsearch中不需要定义Mapping映射(即关系型数据库的表、字段等),在文档写入Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。
动态映射规则如下:
静态映射是在Elasticsearch中也可以事先定义好映射,包含文档的各字段类型、分词器等,这种方式称之为静态映射。
1、设置文档映射
PUT /es_db
{
"mappings":{
"properties":{
"name":{"type":"keyword","index":true,"store":true},
"sex":{"type":"integer","index":true,"store":true},
"age":{"type":"integer","index":true,"store":true},
"book":{"type":"text","index":true,"store":true,"analyzer":"ik_smart","search_analyzer":"ik_smart"},
"address":{"type":"text","index":true,"store":true}
}
}
}
GET /es_db/_doc/_search
{
"query":{
"match_all":{}
}
1、模糊匹配
模糊匹配主要是针对文本类型的字段,文本类型的字段会对内容进行分词,对查询时,也会对搜索条件进行分词,然后通过倒排索引查找到匹配的数据,模糊匹配主要通过match等参数来实现
match的复杂用法:match条件还支持以下参数:
2、精确匹配
组合条件查询是将叶子条件查询语句进行组合而形成的一个完整的查询条件
must/filter/shoud/must_not 等的子条件是通过 term/terms/range/ids/exists/match 等叶子条件为参数的
注:以上参数,当只有一个搜索条件时,must等对应的是一个对象,当是多个条件时,对应的是一个数组
query DSL
在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?”
如何验证匹配很好理解,如何计算相关度呢?ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。
filter DSL
在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”
答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。
过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用must_not或者filter
另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。
Query方式查询:案例
1、根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会采用精确匹配
注意: 采用term精确查询, 查询字段映射类型属于为keyword.
POST /es_db/_doc/_search
{
"query": {
"term": {
"name": "admin"
}
}
SQL: select * from student where name = 'admin'
2、根据备注信息模糊查询 match, match会根据该字段的分词器,进行分词查询
POST /es_db/_doc/_search
{
"from": 0,
"size": 2,
"query": {
"match": {
"address": "广州"
}
}
SQL: select * from user where address like '%广州%' limit 0, 2
3、多字段模糊匹配查询与精准查询 multi_match
POST /es_db/_doc/_search
{
"query":{
"multi_match":{
"query":"张三",
"fields":["address","name"]
}
}
SQL: select * from student where name like '%张三%' or address like '%张三%'
4、未指定字段条件查询 query_string , 含 AND 与 OR 条件
POST /es_db/_doc/_search
{
"query":{
"query_string":{
"query":"广州 OR 长沙"
}
}
5、指定字段条件查询 query_string , 含 AND 与 OR 条件
POST /es_db/_doc/_search
{
"query":{
"query_string":{
"query":"admin OR 长沙",
"fields":["name","address"]
}
}
6、范围查询
POST /es_db/_doc/_search
{
"query" : {
"range" : {
"age" : {
"gte":25,
"lte":28
}
}
}
SQL: select * from user where age between 25 and 28
7、分页、输出字段、排序综合查询
POST /es_db/_doc/_search
{
"query" : {
"range" : {
"age" : {
"gte":25,
"lte":28
}
}
},
"from": 0,
"size": 2,
"_source": ["name", "age", "book"],
"sort": {"age":"desc"}
Filter过滤器方式查询,它的查询不会计算相关性分值,也不会对结果进行排序, 因此效率会高一点,查询的结果可以被缓存。
Filter Context 对数据进行过滤
POST /es_db/_doc/_search
{
"query" : {
"bool" : {
"filter" : {
"term":{
"age":25
}
}
}
}
POST _reindex
{
"source": {
"index": "db_index"
},
"dest": {
"index": "db_index_2"
}
}
DELETE /db_index
PU /db_index_2/_alias/db_index
{
"query": {
"bool": {
"should": [{
"match": {
"title": "文章"
}
},
{
"match": {
"content": "文章"
}
}
]
}
},
"highlight": {
"fields": {
"title": {},
"content": {}
}
}
}
}
如果在搜索的结果document中,需要remark字段中包含多个搜索词条中的一定比例,可以使用下述语法实现搜索。其中minimum_should_match可以使用百分比或固定数字。百分比代表query搜索条件中词条百分比,如果无法整除,向下匹配(如,query条件有3个单词,如果使用百分比提供精准度计算,那么是无法除尽的,如果需要至少匹配两个单词,则需要用67%来进行描述。如果使用66%描述,ES则认为匹配一个单词即可。)。固定数字代表query搜索条件中的词条,至少需要匹配多少个。
GET /es_db/_search
{
"query": {
"match": {
"remark": {
"query": "java architect assistant",
"minimum_should_match": "68%"
}
}
}
如果使用should+bool搜索的话,也可以控制搜索条件的匹配度。
具体如下:下述案例代表搜索的document中的remark字段中,必须匹配java、developer、assistant三个词条中的至少2个。
GET /es_db/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"remark": "java"
}
},
{
"match": {
"remark": "developer"
}
},
{
"match": {
"remark": "assistant"
}
}
],
"minimum_should_match": 2
}
}
GET /es_db/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"remark": "java"
}
}
],
"should": [
{
"match": {
"remark": {
"query": "developer",
"boost" : 1
}
}
},
{
"match": {
"remark": {
"query": "architect",
"boost" : 3
}
}
}
]
}
}
}