Elasticsearch全⽂检索

news/2024/7/7 5:49:09 标签: elasticsearch, 大数据, 搜索引擎

以下说明:其中比喻都是以mysql为模板进行比较说明 

一.lucene

  1.jar包环境准备

   <!-- 引入Lucene核心包及分词器包 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>4.10.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>4.10.3</version>
        </dependency>
       <!-- IK中文分词器 -->
        <dependency>
            <groupId>com.janeluo</groupId>
            <artifactId>ikanalyzer</artifactId>
            <version>2012_u6</version>
        </dependency>
3. 将项⽬⾃动⽣成的 application.properties ⽂件后缀改为 yml 类型。并添加数据库连接配置。
server:
  port: 9000
Spring:
  application:
    name: yx-lucene
  datasource:
#    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/es_db?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
    username: root
    password: 123
# 开启驼峰命名匹配映射
mybatis:
  configuration:
    map-underscore-to-camel-case: true

二。代码如下

package com.example.demo.test;

import com.example.demo.pojo.JobInfo;
import com.example.demo.sercice.JobInfoService;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;
import java.util.List;
@SpringBootTest
public class LuceneTests {
 @Autowired
 private JobInfoService jobInfoService;
 @Test
 public void createIndex() throws IOException {
 // 1.指定索引⽂件存储的位置
 Directory directory = FSDirectory.open(new File("C:\\Users\\Lenovo\\Desktop\\java的复习\\四阶段\\Elasticsearch课前资料\\文档"));
 // 2.配置版本和分词器
// Analyzer analyzer = new StandardAnalyzer(); // 标准分词器默认提供的
  IKAnalyzer analyzer = new IKAnalyzer(); //中文的Ik分词器
  IndexWriterConfig config = new IndexWriterConfig(Version.LATEST,analyzer);
 // 3.创建⼀个⽤来创建索引的对象IndexWriter
  //参数1:表示索引文件的目标位置,参数2表示按哪个分词器写出数据
 IndexWriter indexWriter = new IndexWriter(directory,config);
 indexWriter.deleteAll(); // 先删除索引
 // 4.获取原始数据
 List<JobInfo> jobInfoList = jobInfoService.selectAll();
 // 有多少的数据就应该构建多少lucene的⽂档对象document
 for (JobInfo jobInfo : jobInfoList) {
 Document document = new Document();
 // 域名、值、源数据是否存储 Yes表示永久在索引库中存储,No:表示不永久保存
 document.add(new LongField("id", jobInfo.getId(), Field.Store.YES));
 document.add(new TextField("companyName", jobInfo.getCompanyName(), Field.Store.YES));
  document.add(new TextField("companyAddr", jobInfo.getCompanyAddr(), Field.Store.YES));
  document.add(new TextField("companyInfo", jobInfo.getCompanyInfo(), Field.Store.YES));
  document.add(new TextField("jobName", jobInfo.getJobName(), Field.Store.YES));
  document.add(new TextField("jobAddr", jobInfo.getJobAddr(), Field.Store.YES));
  document.add(new TextField("jobInfo", jobInfo.getJobInfo(), Field.Store.YES));
  document.add(new IntField("salaryMin", jobInfo.getSalaryMin(), Field.Store.YES));
  document.add(new IntField("salaryMax", jobInfo.getSalaryMax(), Field.Store.YES));
  document.add(new StringField("url", jobInfo.getUrl(), Field.Store.YES));
  document.add(new StringField("time", jobInfo.getTime(), Field.Store.YES));
  // StringField不需要分词时使⽤,举例:url、电话号码、身份证号
  indexWriter.addDocument(document);
 }
  // 必须要关闭资源
  indexWriter.close();
 }

 @Test
 public void queryIndex() throws IOException {
  // 1.指定索引⽂件存储的位置
  Directory directory = FSDirectory.open(new File("C:\\Users\\Lenovo\\Desktop\\java的复习\\四阶段\\Elasticsearch课前资料\\文档"));
  // 2.创建⼀个⽤来读取索引的对象IndexReader
  IndexReader indexReader = DirectoryReader.open(directory);
  // 3.创建⼀个⽤来查询索引的对象IndexSearcher
  IndexSearcher indexSearcher = new IndexSearcher(indexReader);
  // 使⽤term查询:指定查询的域名和关键字
  // 使⽤"北京"关键词搜索没有符合的结果
   Query query = new TermQuery(new Term("companyName", "北京"));
//   Query query = new TermQuery(new Term("companyName", "北"));
  // 第⼆个参数:最多显示多少条数据
  TopDocs topDocs = indexSearcher.search(query, 100);
  int totalHits = topDocs.totalHits;
  // 查询的总数量
  System.out.println("符合条件的总数:" + totalHits);
  System.out.println("maxScore="+topDocs.getMaxScore());
  ScoreDoc[] scoreDocs = topDocs.scoreDocs;
  // 获取命中的⽂档,存储的是⽂档的id
  for (ScoreDoc scoreDoc : scoreDocs) {
   int docID = scoreDoc.doc; // 根据id查询⽂档
   Document document = indexSearcher.doc(docID);
   System.out.println( "id: " + document.get("id"));
   System.out.println( "companyName: " + document.get("companyName"));
   System.out.println( "companyAddr: " + document.get("companyAddr"));
   System.out.println( "jobName: " + document.get("jobName"));
   System.out.println("----------------------------------------------");
  }

 }
}

三.解析代码

 二.Kibana(重点)

使⽤Kibana对索引库操作

所有⽂档在写⼊索引前都将被分析,⽤户可以设置⼀些参数,决定如何将输⼊⽂本分割为词条,哪些词条应该被过滤掉,或哪些附加处理有必要被调⽤(⽐如移除HTML标签)。这就是映射扮演的⻆⾊,存储分析链所需的所有信息。Elasticsearch也是基于Lucene的全⽂检索库,本质也是存储数据,很多概念与MySQL类似的。对⽐关系:

settings:就是索引库设置,其中可以定义索引库的各种属性,⽬前我们可以不设置,都⾛默认。

索引库可以理解为mysql的数据库

1.使⽤Kibana创建索引库

PUT / 索引库名

查看索引库

GET请求可以帮我们查看索引信息,语法格式:

GET / 索引库名
查询 my_ip_addr 索引库中的数据。
GET /库名 / _search

删除索引库

删除索引使⽤ DELETE 请求。语法格式
DELETE / 索引库名

2.类型及映射操作(相当于对数据库中表的操作)

创建字段映射(创建表)

 属性描述如下

 查看映射关系 (换成mysql相当于获取到库里面所有表的字段信息)

GET / 索引库名 / _mapping
查看某个索引库中的所有类型的映射(相当于查询具体表的字段信息)
GET / 索引库名 / _mapping / 类型名

一次性创建索引库和类型

1.直接制定索引库中的类型, 基本语法⻅下:

 新增⽂档(表数据)

 1.新增⽂档(表数据)并随机⽣成id

2. 新增⽂档(表数据)并⾃定义id

 3.1查看文档(表数据)

GET /索引名(数据库名) /表名 /数据Id

3.2查看文档(表)所有数据

GET /索引名(数据库名)/表名/_source

4.修改数据

PUT 表示修改⽂档。不过修改必须指定 id 。分为以下两种情况:
如果 id 对应的⽂档存在,则修改。
如果 id 对应的⽂档不存在,则新增。

(这里想吐槽下,如果你不是随机生成ID的画直接用put来新增和修改,put岂不是能代替post) 

5.删除数据

删除使⽤ DELETE 请求,同样需要根据 id 进⾏删除。语法格式:
DELETE / 索引库名 / 类型名 / id
删除数据出错问题

 经查阅资料发现,此问题是由于ES数据存储磁盘剩余空间过少导致的。即ES存在⼀种flood_stage的机制。默认的 磁盘空间设置为95%,当磁盘占⽤超过此值阈值时,将会触发flood_stage机制,ES强制将各索引

index.blocks.read_only_allow_delete设置为true,即ES索引均被设置为仅允许只读只删,不允许新增。
2. 解决⽅法

1.kibana中执⾏以下命令。

PUT / yx / _settings
{
"index.blocks.read_only_allow_delete" : null
}

 说明:执⾏完以后,⽆需重启

2. 或者主机上直接执⾏如下命令。
curl -XPUT -H "Content-Type: application/json" http://localhost:9200/_all/_settings -d
'{"index.blocks.read_only_allow_delete": null}'
curl - X PUT "localhost:9200/twitter/_settings?pretty" - H 'Content-Type:
application/json' - d '
{
"index.blocks.read_only_allow_delete" : null
}
'
说明:以上两种⽅式⼆选其⼀。

6.智能判断

刚刚我们在新增数据时,添加的字段都是提前在类型中定义过的,如果我们添加的字段并没有提前定义过,能够成 功吗?
事实上 Elasticsearch ⾮常智能,你不需要给索引库设置任何 mapping 映射,它也可以根据你输⼊的数据来判断类型,动态添加数据映射
在对 subTitle 字段做数据初始化的时候,设置的是字符串类型数据, ES ⽆法智能判断,它就会存⼊两种字段类型。
例如:
subtitle text 类型
subtitle.keyword keyword 类型
这种智能映射,底层原理是动态模板映射,如果我们想修改这种智能映射的规则,其实只要修改动态模板即可

7.动态模板

动态模板允许您更好地控制 Elasticsearch 如何在默认动态字段映射规则之外映射数据。通过将动态参数设置为 true 或runtime ,可以启⽤动态映射。然后,您可以使⽤动态模板定义⾃定义映射,这些映射可以应⽤于基于匹配条件 动态添加的字段
举例,我们可以把所有未映射的 string 类型数据⾃动映射为 keyword 类型

这样,未知的 string 类型数据就不会被映射为 text keyword 并存,⽽是统⼀以 keyword 来处理
附上以上代码
PUT ytr
{
 "mappings": {
 "goods": {
 "properties": {
 "title": {
 "type": "text",
 "analyzer": "ik_max_word"
 }
 },
 "dynamic_templates": [
 {
 "strings": {
 "match_mapping_type": "string",
 "mapping": {
 "type": "keyword",
 "index": false,
 "store": true
 }
 }
 }
 ]
 }
 }
}

三。(重点)查询是Elasticsearch中需要重点掌握的内容。我们从四个模块来学习Elasticsearch的查询功能。

1.基本查询

 

 1.1查询所有(match_all)

 1.2匹配查询(match)

match类型查询,会把查询条件进⾏分词,然后进⾏查询,多个词条之间是or的关系

 在上⾯的案例中,不仅会查询到电视,⽽且与⼩⽶相关的都会查询到,多个词之间是OR的关系

某些情况下,我们需要更精确查找

 

1.3term 查询被⽤于精确值匹配,这些精确值可能是数字、时间、布尔或者那些未分词的字符串, keyword 类型的字符 串

 1.3布尔组合(bool)

bool 把各种其它查询通过 must (与)、 must_not (⾮)、 should (或)的⽅式进⾏组合

相当于select * from yx where title="大米" and   title="电视"  and title !="手机"

 1.4范围查询(range)

range 查询找出那些落在指定区间内的数字或者时间

 1.6模糊查询(fuzzy)

fuzzy查询是term查询的模糊等价,很少直接使⽤它

fuzzy 查询是 term 查询的模糊等价。它允许⽤户搜索词条与实际词条的拼写出现偏差,但是偏差的编辑距离不得超 过2

 2.结果过滤

2.1获取其中的部分字段,我们可以添加 _source 的过滤

 2.2指定includesexcludes

 

 3 过滤(filter)

3.1条件查询中进⾏过滤

3.2⽆查询条件直接过滤

如果⼀次查询只有过滤,没有查询条件,不希望进⾏评分,我们可以使⽤ constant_score 取代只有 fifi lter 语句的 bool 查询。在性能上是完全相同的,但对于提⾼查询简洁性和清晰度有很⼤帮助。

 4 结果排序

单字段排序

sort 可以让我们按照不同的字段进⾏排序,并且通过 order 指定排序的⽅式

 

 多字段排序

 5.分⻚查询

 

 6 ⾼亮显示

 4.聚合aggregations

 

 聚合为桶

 桶内度量

 


http://www.niftyadmin.cn/n/1534259.html

相关文章

Ubuntu下不能复制粘贴文件的问题

1.先复制要粘贴的文件 2.转到要粘贴的路径下&#xff0c;打开终端&#xff0c;输入 sudo nautilus3.然后粘贴。

惠惠网发布2013年1-2月份《网购价格不完全报告》

惠惠网今天发布了 2013 年 1-2 月份的《网购价格不完全报告》&#xff0c;报告统计了 274 个商城的 30 余万商品在 2013 年 1-2 月份的公开信息。统计显示&#xff0c;受春节影响&#xff0c;1-2 月商品价格变动不大&#xff0c;网购 CPI 环比下降 0.3%&#xff0c;2 月电商日均…

【Java面试题】23 java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?...

java5 以前&#xff0c; 有如下两种&#xff1a;第一种&#xff1a;new Thread(){}.start();这表示调用 Thread 子类对象的 run 方法&#xff0c; new Thread(){}表示一个Thread 的匿名子类的实例对象&#xff0c; 子类加上 run 方法后的代码如下&#xff1a; new Thread(){pub…

一个狗血的mysql编码错误

执行查询语句总是报错&#xff0c;某个查询语句字段编码错误。 各种修改那个表没用&#xff0c; 最后发现是创建schemas的时候没有加编码 应该由 CREATE SCHEMA new_schema;改为 CREATE SCHEMA new_schema default charsetutf8mb4; 浪费了半天时间呀。。转载于:https://www.cnb…

Linux下C++热加载实例

假设一种环境&#xff0c;我们要对服务热拔插一个动态库(.so文件)&#xff0c;所要考虑的是多线程环境的兼容&#xff0c;不会因为动态库替换后造成栈损毁而崩溃。 这边想到的方法就是封装一个dlopen过程作为对象实例加载&#xff08;见load_so.h&#xff09;&#xff0c;当发出…

二, 连接Oracle 二

一&#xff0c;sqlplus操作 文件操作命令 1.start和 说明: 运行sql脚本 案例: sql> home/a.sql或是sql>start home/a.sql 2.edit 说明: 该命令可以编辑指定的sql脚本 案例: sql>edit home/a.sql,这样会把home/a.sql 这个文件打开 3.spool 说明: 该命令可以将s…