检索作为应用场景比较普遍的一种服务,当数据量小时,可以采用模糊查询等操作;MongoDB 内置的正则匹配搜索、text索引、search 关键字等也可以来解决. 面临海量数据和高并发时,常用 ElasticSearch、 lucene 等方案. 不过,ES 的运行对内存有最低限额要求,推荐是 2G 以上,且需要额外的磁盘空间做持久化存储.
此外,Redisearch 也是一个高效的内存存储的高性能全文检索库,适用于数据量适中、内存和存储空间有限的场景.
Elasticsearch 查询是近实时,但写入速度很慢,只是读取数据快,比较依赖内存提高性能./
1. Docker - ES
[1] - 拉取 ES 镜像
docker pull elasticsearch:7.9.0
[2] - 运行 ES 镜像
#单节点模式
docker run --name es7.9 \
-p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-v /data:/data \
-v /path/to/es/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-d elasticsearch:7.9.0
容器启动成功,浏览器查看:http://localhost:9200
1.1. 配置 ES
ES 的配置文件格式为 YAML,类似于 Django 配置的 settings 和 Flask 配置的 Config.
ES 首先找到 elasticsearch.yml,根据指定的参数运行服务.
elasticsearch.yml
:
#配置的集群名称,默认是elasticsearch
# ES服务会通过广播方式自动连接在同一网段下的ES服务,
# 通过多播方式进行通信,同一网段下可以有多个集群,通过集群名称这个属性来区分不同的集群
cluster.name: elasticsearch
#当前配置所在机器的节点名
node.name: "Franz Kafka"
#指定该节点是否有资格被选举成为node(注意这里只是设置成有资格),默认true
node.master: true
#指定该节点是否存储索引数据,默认为true
node.data: true
#设置默认索引分片个数,默认为5片. 7.X版本以上配置无效
index.number_of_shards: 5
#设置默认索引副本个数,默认为1个副本. 7.x版本以上配置无效
index.number_of_replicas: 1
#设置配置文件的存储路径,默认ES根目录下的config文件夹
path.conf: /path/to/conf
#设置索引数据的存储路径
path.data: /path/to/data
#设置临时文件的存储路径
path.work: /path/to/work
#设置日志文件的存储路径
path.logs: /path/to/logs
#设置插件的存放路径
path.plugins: /path/to/plugins
#设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0,绑定这台机器的任何一个ip
network.bind_host: 192.168.0.1
#设置其它节点和该节点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址
network.publish_host: 192.168.0.1
#用来同时设置bind_host和publish_host两个参数
network.host: 192.168.0.1
#设置节点之间交互的tcp端口,默认是9300
transport.tcp.port: 9300
#设置是否压缩tcp传输时的数据,默认为false,不压缩
transport.tcp.compress: true
#设置对外服务的http端口,默认为9200
http.port: 9200
#设置内容的最大容量,默认100mb
http.max_content_length: 100mb
#是否使用http协议对外提供服务,默认为true,开启
http.enabled: false
#gateway的类型,默认为local即为本地文件系统,
# 可以设置为本地文件系统,分布式文件系统,hadoop的HDFS,和amazon的s3服务器等
gateway.type: local
#初始化数据恢复时,并发恢复线程的个数,默认为4
cluster.routing.allocation.node_initial_primaries_recoveries: 4
#添加删除节点或负载均衡时并发恢复线程的个数,默认为4
cluster.routing.allocation.node_concurrent_recoveries: 2
#设置数据恢复时限制的带宽,如入100mb,默认为0,即无限制
indices.recovery.max_size_per_sec: 0
#设置限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5
indices.recovery.concurrent_streams: 5
#设置保证集群中的节点可以知道其它N个有master资格的节点,默认为1,
# 对于大的集群来说,可以设置大一点的值(2-4).7.x版本无效
discovery.zen.minimum_master_nodes: 1
#设置集群中自动发现其它节点时ping连接超时时间,默认为3秒,
# 对于比较差的网络环境可以高点的值来防止自动发现时出错. 7.x版本无效
discovery.zen.ping.timeout: 3s
#设置是否打开多播发现节点,默认是true. 7.x版本无效
discovery.zen.ping.multicast.enabled: false
#设置集群中master节点的初始列表,可以通过这些节点来自动发现新加入集群的节点. 7.x版本无效
discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]
#在启动此节点时传递要执行发现的主机的初始列表
discovery.seed_hosts
#使用初始的一组符合主节点条件的节点引导集群
cluster.initial_master_nodes
2. Python - ES
安装:
pip install elasticsearch
测试脚本 test.py
:
from elasticsearch import Elasticsearch
#链接ES
es = Elasticsearch(hosts=[{"host":' 192.168.1.101', "port": 9200}])
#创建索引Index,命名为demo
demo_index = es.indices.create(index='demo', ignore=400)
print('[INFO]Create Index: ', demo_index)
#删除索引
demo_index = es.indices.delete(index='demo', ignore=[400, 404])
print('[INFO]Del Index: ', demo_index)
#插入数据,类似于MongoDB doc 插入,可以直接插入结构化字典数据
# 可以调用index()会自动生成一个唯一id
doc = {'text1': 'hello demo text 1',
'text2': 'hello demo text 2',
'text3': 'hello demo text 3', }
demo_index = es.index(index='demo',body=doc)
print('[INFO]Insert Data: ', demo_index)
#修改数据
doc = {'text2':"hello es demo text 2"}
demo_index = es.index(index='demo',body=data, id='3lKZ2IzTUJ1UWFFNndZT')
#demo_index = es.delete(index='demo',body=data, id='3lKZ2IzTUJ1UWFFNndZT')
print('[INFO]Modify Data: ', demo_index)
#查询 - 全量查询
demo_index = es.search(index='demo')
print('[INFO]Search All Data: ', demo_index)
#全文检索
mapping = {
'query': {
'match': {
'text2': 'es 2'
}
}
}
demo_index = es.search(index='demo',body=mapping)
print('[INFO]Search Data: ', demo_index)