es multi match_PHP 的ES搜索操作

283badc8a815c8bb0bdd85ea831dc8e9.png

原文:https://blog.csdn.net/JineD/article/details/106650695

首先从ES的支持的字段说起,ES文档中字段有多种类型 官方文档。这几个比较常用:text,keyword,integer,float,boolean,object,geo_point(地理坐标),geo_shape(描述地理区域),date.注:不要以为date只能表示 2015-01-01 这种类型,2015/01/01 12:10:30这种类型也一样可以,不像MySQL里面时间还分很多种细分的类型,ES就一个date类型。注意:这里没有列出array,在ES中,array不是一种单独的类型,但是你可以往ES里面存数组,这个地方有点难以理解,举个例子:文档里面我要定义一个字段叫 friends ,用来存储用户的朋友列表,用 text 类型定义字段:
'friends' => [    'type' => 'text']
看似这仅仅定义了一个text类型的字段,并不是我们想要的数组,重点解释来了,虽然我们的friends是字符串类型,但是我们在存入数据的时候 往 friends里面存储两个或者三个字符串,他就变成数组了!其实这句话描述还是不准确,不是从字符串变成数组,而是多个字符串组成了一个数组!插入数据:
$this->putDoc([    'first_name' => $this->faker->name,    'last_name' => $this->faker->name,    'age' => $this->faker->numberBetween(20,80),    'height' => (float)($this->faker->numberBetween(160,200)/100),    'friends' => [        $this->faker->name(),        $this->faker->name(),        $this->faker->name(),        $this->faker->name()    ]]);
这个putDoc来得有点突然是不是?因为这是延续上一篇文章的续集,请看上一篇文章 使用PHP操作ElasticSearch。注意:faker是用来随机生成数据的,详细信息参考谷歌。你看,friends明明是 text 类型,但是我在插入的时候插入了多条数据,他变成了一个字符串类型的集合,前面我说他是数组,这个地方我把他说成是集合,这回更准确了,因为数组在ES中查询是不能保证顺序的,所以集合更准确,官方文档中也表示他更像集合。再说一下object,模板里面这样定义:
'info' => [    'type' => 'object',    'properties' => [        'country' => [            'type' => 'text',            'analyzer' => 'ik_max_word'        ],        'sex' => [            'type' => 'keyword'        ]    ]]
这里定义了一个对象文档,指定了下面两个属性的基本信息,但是不代表这个对象就只能存储两个属性,比如我还可以在添加文档的时候往里面添加一个skin 肤色的字段,完全没有问题,只不过这里定义的两个字段我们设置了类型和具体的analyzer,没有在这里定义,但是我们实际上添加了的字段比如skin,ES会自动设置正确的类型,以及默认的analyzer。存入数据:
'info' => [    'country' => ['中国','印度','法国','英国','瑞士','刚果共和国'][random_int(0,5)],    'sex' => ['男','女'][random_int(0,1)],    'skin' => ['白','黑','黄'][random_int(0,2)],]
还有一个keyword,他和text都表示字符串,区别在于 keyword里面的值不会被分词器分词,text里面的值会被分词器智能拆分,记住这一点,这一点非常重要,后面还会讲到这个区别。在定义text字段的时候 analyzer和index你需要清楚的地方:
'last_name' => [    'type' => 'text',    //'analyzer' => 'standard', // 这个地方不设置analyzer会默认standard    //'index' => false]
analyzer不设置analyzer会默认standard。对于老版本的 ES,这里的index允许设置为 analyzed/not_analyzed/no,大部分网络上的文章都是这样讲的,但是,最新版本已经移除了这些选项,现在只能是 true或false,所以我建议当你有一点基础后,通读一下官方最新文档,虽然是英文的。如果这里设置为false,这个字段不加入索引,不能在查询条件中出现,默认为true等一下,这里突然发现有点不对劲,以前可以设置 分析/不分析/不索引,现在只能设置索引和不索引了,如果想实现索引且不分析,那keyword类型刚好符合,而text字段是为分析而生的。ES中的搜索分两个概念,匹配和过滤匹配通常针对的是 text 类型的字段,而过滤针通常对的精确的类型,比如 integer,keyword,date等,之所以加了通常二字,说明他们之间没有明确的规定,匹配可以去匹配data,integer等类型,过滤也可以去过滤text字段,通过匹配的方式去找精确类型通常不会出现什么问题,通过过滤去找text类型的数据通常会得到意外的结果。谨记:如果没有特殊情况,匹配针对text类型,过滤针对其他类型,但是对于精确类型使用过滤的性能通常比匹配更高,所以能使用过滤的地方都过滤。注意:这里要区别一下MySQL中的过滤概念,MySQL中的过滤是对查找后的数据进行过滤,而在ES中,过滤和匹配都等同于MySQL中的查找,匹配适合查找模糊数据,过滤适合查找精确数据而已。为了简化代码,下面的搜索都基于一下这份代码,更改的部分只是 $query:
$params = [    'index' => $this->index,    'type' => $this->type,    'body' => array_merge([        'from' => $from,        'size' => $size    ],$query)];
常用的过滤:term(精确查找)查找倪玲为44的数据
$query = [    'query' => [        'term' => [            'age' => 44        ]    ]];
terms(精确查找多个字段)查找年龄为 44或55或66的数据
$query = [    'query' => [        'terms' => [            'age' => [44,55,66]        ]    ]];
range(范围查找)
$query = [    'query' => [        'range' => [            'age' => [                'gt' => 43,                'lt' => 45            ]        ]    ]];
exists(等同于MySQL中的 is not null),查找存在age属性的文档
$query = [    'query' => [        'exists' => [            'field' => 'age'        ]    ]];
missing(等同于 MySQL中的 is null),注意:这个过滤方法在2.x版本就废弃了,请使用 must_not 嵌套 exists 来实现bool(用来组合其他过滤条件,包含 must,must_not,should操作)
$query = [    'query' => [        'bool' => [            'should' => [                'range' => [                    'height' => ['gt' => 1.8]                ]            ],            'must_not' => [                'term' => [                    'info.sex' => '女'                ]            ],            'must' => [                [                    'term' => [                        'info.country' => '法国'                    ]                ],                [                    'term' => [                        'info.skin' => '白'                    ]                ]            ]        ]    ]];
上面这个查询的意思是,身高应该大于1.8,性别不能是女,国家是法国且肤色是黑色。这里country实际上是text类型,但是我任然通过过滤的方法找到了正确的值,但是这种方式是非常危险的,这里之所以找到了正确的值,是因为country类型很简单,碰巧analyzer(这里用的ik,如果是standard就没那么好运了)没有对其进行拆分。常用的查询:match(匹配一个字段)
$query = [    'query' => [        'match' => [            'height' => '1.8'        ]    ]];
match_all(匹配所有文档,相当于没有条件)等于是 $query = []multi_match(匹配多个字段)匹配姓和名里面包含 'Riley Libby Preston' 的数据
$query = [    'query' => [        'multi_match' => [            'query' => 'Riley Libby Preston',            'fields' => ['first_name','last_name']        ]    ]];
bool(用来组合其他匹配条件,包含 must,must_not,should操作)
$query = [    'query' => [        'bool' => [            'should' => [                'match' => [                    'height' => '1.8'                ]            ],            'must_not' => [                'match' => [                    'info.sex' => '男'                ]            ]        ]    ]];
在实际使用中,匹配和过滤都是混合搭配使用的,比如:
$query = [    'query' => [        'bool' => [            'should' => [                'match' => [                    'height' => '1.8'                ]            ],            'must_not' => [                'term' => [                    'info.sex' => '女'                ]            ],            'must' => [                [                    'match' => [                        'info.country' => '法国'                    ]                ],                [                    'match' => [                        'info.skin' => '白'                    ]                ]            ]        ]    ]];
match时常会出现一些怪异的现象,如果你不清楚你用的analyzer,比如这个例子:
$query = [    'query' => [        'bool' => [            'must' => [                [                    'match' => [                        'last_name' => 'Hamill'                    ]                ],                [                    'match' => [                        'info.country' => '法国'                    ]                ]            ]        ]    ]];
这个查询的需求是选出last_name中匹配到Hamill并且国家匹配到法国的结果,但是查询的结果是这样的,last_name 的中包含 Hamill,在我们意料之中,但是 country出现了英国,法国等很多国家,这个太意外了,现在来改造一下这个 $query,很小的改造,只需要把法国改成法,再次查询,这次的结果完美的实现了我们的需求。原因在于:文档中的法国二字被analyzer拆分成 (法,国) 存储在索引中,同理,英国被拆分为 (英,国),现在你搜索法国的时候,你的这个搜索词默认会被拆分成 (法,国),然后拿着这两个词去分别查找,第一个法可以匹配所有法国,第二个国字可以匹配到英国,美国等所有包含国字的结果。现在你知道结果的形成原因了。这个很大程度上上取决于你使用的analyzer,不同的analyzer分词的策略不一样,所以你有必要先搞明白你用的分词器。他的大概分词策略,上面这个例子没有指定analyzer,是ES默认的分词器在起作用,当我指定analyzer为 ik_max_word后,情况发生了变化,这个时候法国被当成了一个整体,没有被拆分。可以通过简单的测试来看看具体分词器的分词方式:
$params = [    'body' => [        'analyzer' => 'ik_max_word', //默认 standard        'text' => '我在广场吃着炸鸡'    ]];return $this->EsClient->indices()->analyze($params);
默认分词器standard会把这句话简单的拆分成单个字,而ik相对就更懂中文一点,拆分出来的词更有语义化,大部分的analyzer对英文的分词都基于空格拆分。fbf300c6876c858db432ad897d3ee98c.png773176fbf8d593031ec732c36aab355a.gif05cc9dc6b675ed27ffec76ab8cbc7dc5.png8a0d8a86d8d79880a74d18e0f15a12dc.gif想要获取学习实战、高并发、架构 、笔试面试资料请扫码咨询+薇薇微信

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/552259.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美术学考计算机,艺术设计专业能跨专业考计算机研究生吗?

首先说明一下,除了一些专业壁垒比较高的学科和专业强烈不建议跨学科或者跨专业考研,其他的专业原则上都是可以跨专业考的。哪些算是专业壁垒比较高呢:医学、艺术类(包括音乐、美术等和设计类)、体育类、外语类、军事类。其余的对于想要跨理工…

git 怎么还原历史版本_4. Git--修改/回退等操作

》》点赞,收藏关注,理财&技术不迷路《《我们已经成功地添加并提交了一个readme.txt文件,现在,是时候继续工作了,于是,我们继续修改readme.txt文件,改成如下内容:Git is a distri…

为什么用python写爬虫_零基础,是怎么开始写Python爬虫的

刚开始接触爬虫的时候,简直惊为天人,十几行代码,就可以将无数网页的信息全部获取下来,自动选取网页元素,自动整理成结构化的文件。利用这些数据,可以做很多领域的分析、市场调研,获得很多有价值…

行列式的计算机应用论文结论,【计算机应用论文】建筑耗能计算机模拟分析(共3654字)...

本文作者:王芙蓉、文亮、王涛 单位:西安建筑科技大学建筑学院、中国建筑设计研究院1(略)利用计算机模拟,能够弥补传统设计方法对建筑能耗分析的不足,帮助建筑师直观地判断方案设计对于建筑能耗的影响,从而将建筑能耗成…

datatable怎么根据两列分组_谈谈怎么做服务隔离

来源于公众号孤独烟 ,作者孤独烟引言OK,如下图所示那显而易见,做服务隔离的目的就是避免服务之间相互影响。毕竟谁也不能说自己的微服务百分百可用,如果不做隔离,一旦一个服务出现了问题,整个系统的稳定性都…

position: absolute;_前端性能优化--transform与position

上个星期去yy语音面试&#xff0c;就有一个这样问题&#xff1a; transform与position:absolute 有什么区别? 我回家后查资料发现这道题目其实不简单啊&#xff0c;涉及到重排、重绘、硬件加速等网页优化的知识。首先看一个用top、left实现的动画效果<style>html,body {…

台式计算机总是重启,台式电脑经常自动重启怎么修复

当我们的电脑出现了电脑自动重启的时候&#xff0c;我们就要注意了&#xff0c;说明我们的电脑主机出现问题了&#xff0c;怎么解决呢。下面是学习啦小编为大家整理的关于台式电脑经常自动重启的相关资料&#xff0c;希望对您有所帮助!台式电脑经常自动重启的解决方法方法/步骤…

gan处理自己的数据集_用GAN生成差分隐私数据集

说在前面今天看了 Generating Differentially Private Datasets Using GANS&#xff0c;明天要讨论。老师不知道从哪里挖出了这篇被拒了的文&#xff0c;研究的主题和我们最近的工作非常相关&#xff0c;而且证明非常有趣&#xff0c;大致地看了一下文章的结构觉得没啥问题&…

ipython安装成功后用不了_ipython安装避坑指南

python学习笔记03 本来想着继续给大家介绍python的数据类型&#xff0c;但是IDLE编辑器&#xff08;默认的 Python shell 编辑器&#xff09;太难用了&#xff0c;导致小编没水出来&#xff0c;所以小编决定装一个别的python shell编辑器&#xff0c;这就是ipython&#xff1b;…

如果用户计算机已接入,01计算机基础知识题(50道)

7、在Windows2000中&#xff0c;切换到MS&#xff0d;DOS方式后&#xff0c;返回Windows2000的命令是。8、在“我的电脑”窗口中用鼠标双击“软盘A”图标&#xff0c;将会。习题参考答案三、填空题1&#xff0e;启动 2&#xff0e;软键盘 3&#xff0e;硬盘 4&#xff0e;弹出式…

k1658停运_最新通知!福州这些列车停运!

停运列车1.4月1日至4月7日太原开k903次&#xff0c;4月3日至4月9日厦门北开k904次停运。2.4月1日至4月8日广州东开k297次&#xff0c;4月2日至4月9日厦门北开k298次停运。3.4月4、5、7日厦门开D6214次、福州开D6229次、厦门开D6224次&#xff0c;4月5、6、8日福州开D6219次、厦…

线程执行完之后会释放吗_java多线程并发:CAS+AQS+HashMap+volatile+ThreadLocal,乐分享...

CyclicBarrier、CountDownLatch、Semaphore 的用法CountDownLatch(线程计数器 )CountDownLatch 类位于 java.util.concurrent 包下&#xff0c;利用它可以实现类似计数器的功能。比如有一个任务 A&#xff0c;它要等待其他 4 个任务执行完毕之后才能执行&#xff0c;此时就可以…

计算机应用基础考查方案,《计算机应用基础》考查方案

《计算机应用基础》考查方案 《计算机应用基础》考核方案 制订人&#xff1a;刘久红老师 计算机应用基础科任教师 制订部门&#xff1a;基础课与思政课教学部 制订时间&#xff1a;2012年12月 一&#xff1a;考核依据 计算机应用基础是面向全院各专业开设的一门重要的公共基础课…

mongodb 导出到sqlserver_SQLServer数据导入Mongodb

SQLServer数据导入Mongodb一、思路MongoVUE免费版支持MySQL导入Mongo,所以思路是SQLServer导入MySQL,再从MySQL导入Mongo。二、准备1&#xff0c;安装mysql数据库(我用的是WAMP&#xff0c;集成mysql&#xff0c;phpadmin)&#xff0c;如果需要&#xff0c;建立自己的数据库如M…

用python画长方形_Python+opencv:绘制矩形,编写文本,PythonOpenCV,画,矩形框

#用 OpenCV 标注 bounding box主要用到下面两个工具——cv2.rectangle() 和 cv2.putText()。用法如下&#xff1a; # cv2.rectangle() # 输入参数分别为图像、左上角坐标、右下角坐标、颜色数组、粗细cv2.rectangle(img, (x,y), (xw,yh), (B,G,R), Thickness) # cv2.putText() …

无法启动此程序因为计算机丢失msvcr110.dll,计算机中丢失msvcr110.dll怎么办

我们在打开电脑程序的时候&#xff0c;系统提示无法启动此程序&#xff0c;因为计算机中丢失MSVCR110.dll&#xff0c;尝试重新安装该程序以解决此问题。这是什么情况呢?因为现在所有的5.5环境都是基于vc11的编译脚本下生成的&#xff0c;所以在windows下你得安装相关组件&…

anaconda pandas运行不了_学习python你必须弄懂的 Python、Pycharm、Anaconda 三者之间的关系...

Python作为深度学习和人工智能学习的热门语言&#xff0c;学习一门语言&#xff0c;除了学会其简单的语法之外还需要对其进行运行和实现&#xff0c;才能实现和发挥其功能和作用。下面来介绍运行Python代码常用到的工具总结。一.Python、Pycharm、Anaconda关系介绍1. PythonPyt…

谁先量子计算机谁就,G、IBM、中科院,比一比谁先实现量子计算霸权?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼前天&#xff0c;科技圈的“重磅”、“突破”&#xff0c;可能又是一条“明明每个字都认识”系列的新闻&#xff1a;中科院在5月3日宣布中国建造了世界上第一台超越早期经典计算机的光量子计算机&#xff0c;自主研发10比特超导量子…

java: 程序包com.alibaba.fastjson不存在_Java开发中的异常

NO.1 Java.alng.NullPointerException这个异常大家肯定都经常遇到&#xff0c;异常的解释是 “程序遇上了空指针 “&#xff0c;简单地说就是调用了未经初始化的对象或者是不存在的对象&#xff0c;这个错误经常出现在创建图片&#xff0c;调用数组这些操作中&#xff0c;比如图…

福大计算机课程表,教学文件 - 福州大学电气工程与自动化学院

第一章 总 则第一条教室是学校教书育人的主要场所&#xff0c;是精神文明的窗口之一&#xff0c;为创造优美、文明、卫生的学习环境&#xff0c;保证教学活动的顺利进行&#xff0c;特制定本管理规定。第二条全校公共教学楼教室的使用均由教务处统一安排&#xff0c;多媒体教…