Solr入门级教程

Solr:企业级搜索应用服务器

在海量数据下,对MySQL等数据库进行模糊查询或者条件查询的效率是非常低的。模糊查询会使索引失效而进行全表扫描,所以就需要有东西去提升搜索效率。

SpringBoot中使用Solr
solr查询
// 直接查询总条数
long count =solrTemplate.count(“索引库名称”, query);
// 查询条件:判断当该字段不为空时
Criteria criteria =new Criteria("索引字段").isNotNull();

// 这里的分页是必须设置的,Rows 决定了查询的总数量的大小
Query query = new SimpleQuery();
query.setOffset(0L);
query.setRows(Integer.MAX_VALUE);

// 此处的分页是分组中的分页
// 这里的分页对应的是 groupEntry.getResult().getContent() 中的值,但是即使设置为0,也不会影响  groupEntry.getResult().getTotalElements()
GroupOptions groupOptions = new GroupOptions().addGroupByField("testinfo_devtype");
groupOptions.setOffset(0);
groupOptions.setLimit(0);
query.setGroupOptions(groupOptions);
  1. 导入maven依赖
<!--solr搜索依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
  1. 配置solr地址
spring:
  data:
    solr:
     # Solr的地址
      host: http://localhost:8983/solr
  1. 编写添加方法

    // 批量添加
    @PostMapping("saveAll")
    public void saveDatas() {
        List<Products> list = new ArrayList<>();
        //  创建实体
        Products products1 = new Products();
        products1.setId("1");
        products1.setMdName("rrp");
        products1.setMdCode("B02010130395");
        products1.setMdAge("121.196.150.36");
        Products products2 = new Products();
        products2.setId("2");
        products2.setMdName("yq");
        products2.setMdCode("B02010130395");
        products2.setMdAge("121.196.150.36");
        Products products3 = new Products();
        products3.setId("3");
        products3.setMdName("pg");
        products3.setMdCode("B02010130395");
        products3.setMdAge("121.196.150.36");
        Products products4 = new Products();
        products4.setId("4");
        products4.setMdName("lh");
        products4.setMdCode("B02010140495");
        products3.setMdAge("121.196.150.36");
        list.add(products1);
        list.add(products2);
        list.add(products3);
        list.add(products4);
        // 给索引库添加数据
        UpdateResponse meta_db = solrTemplate.saveBeans("meta_db", list);
        // 提交
        solrTemplate.commit("meta_db");
    }
    
    // 单个添加
    @PostMapping
    public void saveData(){
        //  创建实体
        Products products = new Products();
        products.setId("1");
        products.setMdName("zhangsan");
        products.setMdCode("10");
        products.setMdAge("12");
        // 给索引库添加数据
        UpdateResponse meta_db = solrTemplate.saveBean("meta_db", products);
        // 提交
        solrTemplate.commit("meta_db");
    }
    
  2. 编写solr删除方法

    @DeleteMapping
    public void deleteData() throws Exception {
        // 1. 根据id删除
        solrTemplate.deleteByIds("meta_db",Arrays.asList("12"));
        // 2. 将满足查询条件的全部删除
        SolrDataQuery query = new SimpleQuery();
        // 设置查询条件
        query.addCriteria(Criteria.where("md_code").startsWith("4"));
        solrTemplate.delete("meta_db", query);
        // 提交
        solrTemplate.commit("meta_db");
    }
    
  3. 编写solr查询方法

@GetMapping
public Object select() {
    // 1. 指定主键id查询
    // 参数1:索引库,参数2:指定id,参数3:查询的类型
    Products meta_db = solrTemplate.getById("meta_db", "12", Products.class).get();

    // 2. 根据某个字段简单查询(该字段为索引库(Filed)中的字段)
    // Query : 指定查询条件
    Query query = new SimpleQuery("md_age:19");
    Page<Products> ans = solrTemplate.query("meta_db", query, Products.class);

    // 3. 查询'md_name'字段中包含'测试'的文档(类似于模糊查询?)
    Query queryByTest = new SimpleQuery();
    //  索引库(Filed)中的字段   根据关键字'测试'查询
    queryByTest.addCriteria(new Criteria("md_name").contains("测试"));
    Page<Products> queryByTestResult = solrTemplate.query("meta_db", queryByTest, Products.class);
    //  多条件查询:lessThan() 查询某字段的值小于其参数的所有值
    queryByTest.addCriteria(new Criteria("md_name").contains("测试").and("id").lessThan(13));
    Page<Products> queryByTwoTestResult = solrTemplate.query("meta_db", queryByTest, Products.class);
    //  主要用来快速过滤,配合 query 进行操作
    query = new SimpleQuery("md_code: *4*");
    query.addFilterQuery(FilterQuery.filter(Criteria.where("md_age").contains("19")));
    ans = solrTemplate.query("meta_db", query, Products.class);

    // 4. 查询 只返回指定的字段
    SimpleQuery simpleQuery = new SimpleQuery();
    simpleQuery.addCriteria(Criteria.where("md_age").contains("19"));
    // fl 查询  只返回查询到的数据的‘md_name’字段数据
    simpleQuery.addProjectionOnFields("md_name");
    List<Products> simpleQueryans = solrTemplate.query("meta_db", simpleQuery, Products.class).getContent();

    // 5. 范围查询 排序
    query = new SimpleQuery();
    // 查询id值在12-13之间的数据   参数3,参数4 :分别表示不包含下界 上界,即为开区间
    query.addCriteria(Criteria.where("id").between(12, 14, false, false));
    //  Sort.by() 根据某字段排序  descending() 倒排  ascending() 正排
    query.addSort(Sort.by("id").ascending());
    simpleQueryans = solrTemplate.query("meta_db", query, Products.class).getContent();

    // 6. 分页查询
    query = new SimpleQuery("*:*");
    query.addSort(Sort.by("id").ascending());
    // 指定偏移量,从0开始开训
    query.setOffset(2L);
    // 查询的size数量
    query.setRows(4);
    ans = solrTemplate.queryForPage("meta_db", query, Products.class);
    // 文档数量
    long totalDocNum = ans.getTotalElements();
    // 文档集合
    List<Products> docList = ans.getContent();

    // 7. 分组查询
    query = new SimpleQuery("*:*");
    // addGroupByField() 分组的标准
    // 请注意,分组查询,必须指定 offset/limit, 否则会抛异常,Pageable must not be null!
    // GroupOptions:
    // 必须指定 offset/limit,当两个条件都没有时会抛异常
    // 只指定 offset 时,limit 默认为 1
    // 只指定 limit 时,offset 默认为 0
    GroupOptions groupOptions = new GroupOptions().addGroupByField("md_name").setOffset(0).setLimit(10);
    query.setGroupOptions(groupOptions);

    GroupPage<Products> groupResultans = solrTemplate.queryForGroupPage("meta_db", query, Products.class);
    GroupResult<Products> groupResult = groupResultans.getGroupResult("md_name");

    Page<GroupEntry<Products>> entries = groupResult.getGroupEntries();
    for (GroupEntry<Products> sub : entries) {
        // 分组字段的具体值
        String groupValue = sub.getGroupValue();
        // 组内成员
        Page<Products> contentList = sub.getResult();
        System.out.println("queryGroup v=" + groupValue + " content=" + contentList.getContent());
    }
    return entries;
}
filed字段常用属性

可以为给定字段类型指定的属性为分三大类:

  • 特定于字段类型的类型属性
  • 常规属性,solr支持任何字段类型
  • 字段默认属性,可以在字段类型上指定,将由使用此类型的字段而不是默认行为继承
  1. 常规属性
    name:fieldType的名称。
    class:用于存储和索引此类型数据的类名。
    positionIncreamentGap:对于多值字段,指定多个值之间的距离,以防止虚拟短语匹配。
    autoGeneratePhraseQueries:对于文本字段,如果true,Solr自动为相邻术语生成短语查询。如果为false,术语必须用双引号括起来作为短语。
    synonymQueryStyle:用于组合重叠查询项(即同义词)的分类的查询。

  2. 字段默认属性
    这些属性可以在字段类型上指定,也可以在单个字段上指定,以覆盖字段类型的默认值。

image-20210527092242178

正向索引和反向索引

也可以叫做正排序和倒排序

Solr web管理后台介绍
  1. Dashboard 仪表盘

    显示Solr的基本信息,包含solr版本,包含系统内存和jvm内存的使用情况,jvm参数等

  2. Logging solr的运行日志

    solr的运行日志, 用来查看solr运行是否有警告或者异常,以便及时处理

  3. Core Admin 索引库管理

    索引库管理:

    这个界面很重要,这使多核的配置,索引库的优化等,变得非常简单;
    主要功能包括:

    Add Core(添加核心,即索引库),Unload(卸载核心),Rename(重命名核心),Optimize(优化索引库)。

  4. Core Selector 核心选择器

    1. Overview(概览):查看索引的情况,例如:看看Num docs数量是否增加。包含基本统计如当前文档数;和实例信息如当前核心的配置目录;

    2. Analysis(分析):检验分词效果,用来诊断潜在的 文本分析 的查询/索引问题。注意FieldType需要选定为与被分析内容类型一致。

    3. Query(查询):这是一个查询界面,用的比较多,用来查询索引的文档,包含是否存在,排序是否正确等。稍后会介绍相关的查询参数。

    4. Schema 当前索引库定义显示当前的schema的配置文件,即schema.xml的内容,例如:可以看到schema.xml 中的配置的字段等信息

    5. Documents (索引文档)索引的相关操作,增加,修改,删除等,例如我们要增加一个索引.

    a. 先要在solr 的D:\solr_home\mycore1\conf 的 schema.xml配置文件下,增加相关的字段field,例如:

    <field name="title" type="string" indexed="true" stored="true" required="true" multiValued="false" />
    

    b. 在如下页面,选择/update ,文档格式选择json ,然后submit 提交。这样 索引就增加上了。

    c. 删除所以也是类似,只不过Document(s) 里面的xml一样 ,这个是删除全部的索引 : 注意:这个节点不能少,否则删除动作的事务不会提交。

    注意:如果没有做分词,相关的字段查询是精确匹配的,比如 将q 输入 title:me 即 查询title 为 me 的数据。

入门安装配置
  1. 注意前提是你的电脑上已经有了java和tomcat的环境。

    下载地址

  2. 下载后解压的指定目录

    目录结构如下:

    image-20210513101950481

  3. 进入bin目录,启动solr

    启动命令:solr start

    关闭命令:solr stop -all

    重启solr :solr restart –p p_num

    image-20210513102112630

  4. 打开浏览器访问地址

  5. 创建核心文件夹,名字随意

    image-20210513102528550

  6. 复制配置文件到核心文件夹里

    image-20210513102633253

    image-20210513102715797

  7. 创建Core Admin,先选择Core Admin,填写name与instanceDir,选择Add Core

    image-20210513102937112

  8. 创建doucument表

    image-20210513103243257

  9. 添加字段,注意name不可以重复

    方式1:web端手动添加

    image-20210513103539098

    方式2:配置文件中创建

    <!--name 字段名-->
    <!--type 数据类型-->
    <!--Tokenized 是否分词-->
    <!--uninvertible -->
    <!--indexed 是否为索引-->
    <!--stored 是否存储-->
    <field name="md_code" type="string" uninvertible="true" indexed="true" stored="true"/>
      <field name="md_age" type="string" uninvertible="true" indexed="true" stored="true"/>
      <field name="md_name" type="string" uninvertible="true" indexed="true" stored="true"/>
    
  10. ,选择document,添加数据

    image-20210513103815545

    image-20210513103943687

  11. 查询,可以看到我们导入的数据

    说明:

    status 为 o 表示查询成功 ;

    QTime 表示查询所用时间 ;

    numFound 表示 查询数量

    q 功能很强大,支持模糊查询、关联查询、and和or等。

    image-20210513104210633

    image-20210513104104457

常用命令

也可以通过 solr create -c 来创建项目实例

image-20210513104559289

总结
  1. 安装好solr:启动,默认端口为8983

  2. 使用solr create -c来创建项目实例

  3. 在配置文件中创建索引列

  4. 在SpringBoot中导入maven依赖spring-boot-starter-data-solr

  5. 编写配置类SearchAutoSolrConfig

  6. 实现增删改查(增和改是同一个方法)

solr集成IK分词器
  1. 下载IK分词器,解压,如下图所示:

    image-20210528145453878

  2. 将jar包放到\solr-8.8.2\server\solr-webapp\webapp\WEB-INF\lib目录下

    image-20210528145706617

  3. 将其他文件放到\solr-8.8.2\server\solr-webapp\webapp\WEB-INF\classes目录下

    image-20210528145808872

  4. 进入solr实例目录下,随便一个实例的conf目录下,修改配置文件,将下面的配置添加进文中。

      <!-- ik分词器 -->
    <fieldType name="text_ik" class="solr.TextField">
      <analyzer type="index">
    	  <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
    	  <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
      <analyzer type="query">
    	  <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
    	  <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
    </fieldType>
    <!-- 设置业务系统Field -->
    <field name="item_title" type="text_ik" indexed="true" stored="true"/>
    <field name="item_sell_point" type="text_ik" indexed="true" stored="true"/>
    <field name="item_price"  type="plong" indexed="true" stored="true"/>
    <field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
    <copyField source="item_title" dest="item_keywords"/>
    <copyField source="item_sell_point" dest="item_keywords"/>
    
  5. 测试分词

    image-20210528150239826

查询条件的组装

criteria.where() 自身是不能叠加的

criteria.and() 自身是可以叠加使用。例如

Query query = new SimpleQuery();
Criteria criteria = new Criteria("mdName").isNotNull();
criteria= criteria.and("id").is(1);
criteria= criteria.and("mdName").is("123");
query.addCriteria(criteria);

创作不易,给点鼓励吧👍

WeChat Pay

支付宝打赏

Alipay

微信打赏

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值