文章目录
安装es: 官网下载解压
启动 bin/elasticsearch -d (后台启动)
判断是否成功的标志 curl http://localhost:9200/?pretty
9200是es的默认端口,可以在config/elasticsearch.yml中修改
启动成功如下图所示:

head 插件
head插件是es的一个可视化插件,类似于workbench跟mysql的关系
进入github head github 按照readme 文件安装,我这里选择的是以谷歌浏览器插件的方式安装,如下图

marvel插件
marvel插件主要是用来监控的,也可以用来当console来使用
postman
用于和es交互,发送请求
1. 修改配置文件
在es包下的config目录修改es的默认配置文件elasticsearch.yml,在该文件后追加如下配置
xpack.security.enabled: true
## 加密方式
xpack.license.self_generated.type: basic
xpack.security.transport.ssl.enabled: true
2. 设置密码
重启es让配置文件生效,再到es包下bin目录执行以下命令
.\elasticsearch-setup-passwords interactive
效果如下

3. postman中登录

其他地方也是使用同样的方法登录,用户名为:elastic,密码为:123456
节点 Node、集群 Cluster 和分片 Shards
ElasticSearch 是分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个实例。单个实例称为一个节点(node),一组节点构成一个集群(cluster)。分片是底层的工作单元,文档保存在分片内,分片又被分配到集群内的各个节点里,每个分片仅保存全部数据的一部分。
索引 Index、类型 Type 和文档 Document
如果我们要访问一个文档元数据应该包括囊括 index/type/id 这三种类型
对比 MySQL 数据库:
index → db
type → table
document → row
每一条数据就是一个document, 此处id可以在插入数据时指定,不指定也会自动生成
映射
映射(mapping) 是用来事先定义插入数据中字段的数据类型、字段的权重、分词器等属性,就如同在关系型数据库中创建数据表时会设置字段的类型。在 Elasticsearch 中,映射可分为动态映射和静态映射,静态映射是写入数据之前对字段的属性进行手工设置,动态映射是可直接创建索引并写入文档,文档中字段的类型是 Elasticsearch 自动识别的,不需要在创建索引的时候设置字段的类型。
参考 Elasticsearch 索引映射类型及mapping属性详解
所有语言可以使用 RESTful API 通过端口 9200 和 Elasticsearch 进行通信。一个 Elasticsearch 请求和任何 HTTP 请求一样由若干相同的部件组成:
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
VERB是 HTTP 方法,可选 : GET、 POST、 PUT、 HEAD 或者 DELETEPROTOCOL 即 http 或者 httpsHOST Elasticsearch 集群中任意节点的主机名,用 localhost 代表本地机器上的节点PORT 运行 Elasticsearch HTTP 服务的端口号,默认是 9200PATH API 的终端路径(例如 _count 将返回集群中文档数量)Path 可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvmQUERY_STRING 任意可选的查询字符串参数 (例如 ?pretty 将格式化地输出 JSON 返回值,使其更容易阅读)BODY 一个 JSON 格式的请求体HTTP 命令PUT新建文档, GET 可以用来检索文档,同样的,可以使用 DELETE 命令来删除文档,以及使用 HEAD 指令来检查文档是否存在。如果想更新已存在的文档,只需再次 PUT
下面使用postman和es来交互进行数据创建和查询:
创建数据
创建员工目录,为每个员工的文档(document)建立索引,每个文档包含了相应员工的所有信息
PUT /megacorp/employee/3
{
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about": "I like to build cabinets",
"interests": [ "forestry" ]
}
在postman中操作如下

插入三个数据可以使用head插件查看相关信息:

可以通过http get来获信息
GET /megacorp/employee/1
返回
{
"_index" : "megacorp",
"_type" : "employee",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
}

_index 索引名称
_type 类型名称
_id id(这个id可以自己指定也可以自动生成)
_version 版本号,每次改动会+1
found true表示在document存在
_source document的全部内容
轻量级搜索
查询字符串
GET /megacorp/employee/_search?q=last_name:Smith
返回
{
"took": 31,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.4700036,
"hits": [
{
"_index": "megacorp",
"_type": "employee",
"_id": "1",
"_score": 0.4700036,
"_source": {
"first_name": "John",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [
"sports",
"music"
]
}
},
{
"_index": "megacorp",
"_type": "employee",
"_id": "2",
"_score": 0.4700036,
"_source": {
"first_name": "Jane",
"last_name": "Smith",
"age": 32,
"about": "I like to collect rock albums",
"interests": [
"music"
]
}
}
]
}
}

Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。我们可以这样表示之前关于“Smith”的查询
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}

过滤器
更复杂的搜索,使用过滤器(filter)来实现sql中where的效果,比如:你想要搜索一个叫Smith,且年龄大于30的员工,可以这么检索.
{
"query": {
"bool": {
"filter": {
"range": {
"age": {
"gt": 30
}
}
},
"must": {
"match": {
"last_name": "Smith"
}
}
}
}
}

短语搜索
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}
match_phrase与match的区别在于,前者会把rock climbing(搜索条件)作为一个整体,而后者会命中rock balabala climbing(后者只要命中其中一个词就算命中,比如rock climbing中命中rock就算匹配中了,就会返回结果)

用于搜索单个字段,首先会针对查询语句进行解析(经过 analyzer),主要是对查询语句进行分词,分词后查询语句的任何一个词项被匹配,文档就会被搜到,默认情况下相当于对分词后词项进行 or 匹配操作
GET article/_search
{
"query": {
"match": {
"title": {
"query": "Elasticsearch 查询优化"
}
}
}
}
等同于
GET article/_search
{
"query": {
"match": {
"title": "Elasticsearch 查询优化"
}
}
}
也等同于
GET article/_search
{
"query": {
"match": {
"title": {
"query": "Elasticsearch 查询优化",
"operator": "or"
}
}
}
}
如果要匹配所有关键词使用and
GET article/_search
{
"query": {
"match": {
"title": {
"query": "Elasticsearch 查询优化",
"operator": "and"
}
}
}
}
match_phrase query 首先会把 query 内容分词,分词器可以自定义,同时文档还要满足以下两个条件才会被搜索到:
GET test_idx/test_tp/_search
{
"query": {
"match_phrase": {
"desc": "what life"
}
}
}
term 查询用来查找指定字段中包含给定单词的文档,term 查询语句不被解析,只有查询词和文档中的词精确匹配才会被搜索到,应用场景为查询人名、地名等需要精准匹配的需求
GET books/_search
{
"query": {
"term": {
"title": "思想"
}
}
}
terms 查询是 term 查询的升级,可以用来查询文档中包含多个词的文档。比如,想查询 title 字段中包含关键词 “java” 或 “python” 的文档,构造查询语句如下:
{
"query": {
"terms": {
"title": ["java", "python"]
}
}
}
filter 类似于 SQL 里面的where 语句,和上面的基础查询比起来,也能实现搜索的功能,同时 filter 可以将查询缓存到内存当中,这样可以大大加大下一次的查询速度
下面实现 select document FROM products WHERE price = 20
GET /store/products/_search // store 索引名 products 商品名
{
"query":{
"bool":{
"query":{
"match_all":{} // 匹配所有
}
"filter":{
"term":{
"price":20
}
}
}
}
}
range query 即范围查询,用于匹配在某一范围内的数值型、日期类型或者字符串型字段的文档,比如搜索哪些书籍的价格在 50 到 100之间、哪些书籍的出版时间在 2015 年到 2019 年之间。使用 range 查询只能查询一个字段,不能作用在多个字段上。
range 查询支持的参数有以下几种:
// 查询价格大于 50,小于等于 70 的书籍
GET bookes/_search
{
"query": {
"range": {
"price": {
"gt": 50,
"lte": 70
}
}
}
}
bool query(组合查询)是把任意多个简单查询组合在一起,使用 must、should、must_not、filter 选项来表示简单查询之间的逻辑,每个选项都可以出现 0 次到多次。
bool query 主要通过下列 4 个选项来构建用户想要的布尔查询,每个选项的含义如下:
GET books/_search
{
"query": {
"bool": {
"filter": {
"term": {
"status": 1
}
},
"must_not": {
"range": {
"price": {
"gte": 70
}
}
},
"must": {
"match": {
"title": "java"
}
},
"should": [
{
"match": {
"description": "虚拟机"
}
}
],
"minimum_should_match": 1
}
}
}
wildcard 查询:允许使用通配符 * 和 ? 来进行查询
* 匹配任意一个或多个字符? 匹配任意一个字符GET /library/books/_search
{
“query”:{
"wildcard":{
"preview":"rab*"
}
}
}
boosting 查询用于需要对两个查询的评分进行调整的场景,boosting 查询会把两个查询封装在一起并降低其中一个查询的评分。
boosting 查询包括 positive、negative 和 negative_boost 三个部分,positive 中的查询评分保持不变,negative 中的查询会降低文档评分,negative_boost 指明 negative 中降低的权值。
// 对 2015 年之前出版的书降低评分
GET books/_search
{
"query": {
"boosting": {
"positive": {
"match": {
"title": "python"
}
},
"negative": {
"range": {
"publish_time": {
"lte": "2015-01-01"
}
}
},
"negative_boost": 0.2
}
}
}
boosting 查询中指定了抑制因子为 0.2,publish_time 的值在 2015-01-01 之后的文档得分不变,publish_time 的值在 2015-01-01 之前的文档得分为原得分的 0.2 倍。
使用 price、date 和 _score 进行查询,并且匹配的结果首先按照价格排序,然后按照日期排序,最后按照相关性排序
GET books/_search
{
"query": {
"bool": {
"must": {
"match": { "content": "java" }
},
"filter": {
"term": { "user_id": 4868438 }
}
}
},
"sort": [{
"price": {
"order": "desc"
}
}, {
"date": {
"order": "desc"
}
}, {
"_score": {
"order": "desc"
}
}
]
}
排序条件的顺序是很重要的。结果首先按第一个条件排序,仅当结果集的第一个 sort 值完全相同时才会按照第二个条件进行排序,以此类推
如下图,es中已经存入以下数据,接下来进行增删查改操作

程序如下
import json
import requests
import os
import base64
import logging
LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s"
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
def search_es_match(host="localhost", port="9200", index="megacorp", type="employee", id="", operate="search", search_body=dict()):
'''
host/port: ip和端口号
index: 索引名称
type: es中存储数据的类型,可以为空字符串
id: es存储的数据的id, 如果需要删除或者修改该条数据,必须指定id
operate: 进行何种操作: 插入/修改insert, 查询search, 删除delete
'''
op_map = {"search":"_search", "insert":"", "delete":""}
if operate in op_map:
op = op_map.get(operate)
else:
logging.warn("没有该操作类型: %s"%operate)
return -1
search_url = os.path.join(f"http://{host}:{port}", index, type, id, op )
# 有密码时候带上用户及密码
# auth = str(base64.b64encode(f'{self.username}:{self.password}'.encode('utf-8')), 'utf-8')
# 请求头中带有Authorization
headers = {
"Content-Type": "application/json",
# 'Authorization': f'Basic {auth}'
}
data = json.dumps(search_body)
requests.DEFAULT_RETRIES = 5 # 增加重试连接次数
s = requests.session()
s.keep_alive = False # 关闭多余连接
if operate == "delete":
r = requests.delete(search_url, headers=headers)
else:
r = requests.post(search_url, data=data, headers=headers)
return r.json()
if __name__ == "__main__":
data = {
"query":{
"bool":{
"filter":{
"term":{
"last_name":"smith"
}
},
"must":{
"range":{
"age":{
"gt":25
}
}
},
"should":{
"match":{
"about": "like to"
}
}
}
}
}
data2 = {
"first_name": "Li",
"last_name": "Bai",
"age":72,
"about": "chuang qian ming yue guang"
}
data3 = {
"first_name": "Li",
"last_name": "Bai",
"age":72,
"about": "chuang qian ming yue guang, yi shi di shang shuang"
}
# 插入新数据
ret1 = search_es_match(id="110", operate="insert", search_body=data2)
print(ret1)
# 修改数据
ret2 = search_es_match(id="110", operate="insert", search_body=data3)
print(ret2)
# 删除数据
ret3 = search_es_match(id="110", operate="delete")
print(ret3)
# 查询数据
ret4 = search_es_match(operate="search", search_body=data)
print(ret4)
插入数据
ret1 结果
{'_index': 'megacorp', '_type': 'employee', '_id': '110', '_version': 1, 'result': 'created', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 15, '_primary_term': 5}

修改数据结果
ret2 结果
{'_index': 'megacorp', '_type': 'employee', '_id': '110', '_version': 2, 'result': 'updated', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 16, '_primary_term': 5}

修改内容时,其他不修改的内容也需写入body中,否则默认会赋空值
删除数据结果
ret3 结果
{'_index': 'megacorp', '_type': 'employee', '_id': '110', '_version': 3, 'result': 'deleted', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 17, '_primary_term': 5}

查询数据
{'took': 121,
'timed_out': False,
'_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0},
'hits': {'total': {'value': 1, 'relation': 'eq'},
'max_score': 2.257855,
'hits': [{'_index': 'megacorp', '_type': 'employee', '_id': '2', '_score': 2.257855, '_source': {'first_name': 'Jane', 'last_name': 'Smith', 'age': 32, 'about': 'I like to collect rock albums', 'interests': ['music']}}]}}
参考 python 操作 ElasticSearch 入门
python操作ES数据库
现在es中存储了如下数据

现在用filter方法来查询 last_name=Smith 的数据,如下图,却未查询到相关的数据

我们再把 term 换成 match 方法,可以发现能够查询到两个结果

原因
term是代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词拆解,但是Smith这个词在进行存储的时候,进行了分词处理,这里使用的是默认的分词处理器进行了分词处理,使得存入的时候将Smith 存成了 smith, 如下图所示,我们用_ananlyze方法查看存入形式:

因此我们在用 term 方法查询时,应该查询smith,如下图所示,查询到2个结果

所以,在默认分词方式下,使用term来精确查询需要全部用小写字母来查询
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po