Solr简介

为什么用Solr

海量数据下,关系型数据库的搜索效率比较低,最好使用专用搜索工具搜索

常见所搜解决方案

  • 基于Apache Lucene(全文检索工具库)
  • 谷歌API
  • 百度API

Solr

  • solr基于Apache Lucene构建的用于搜索和分析的开源解决方案
  • solr本质是一个内嵌了Jetty服务器的一个Java web项目,请求Solr中控制器,处理完数据后把结果响应给客户端

正向索引和反向索引

foward index 和 inverted index

正向索引:从文档内容到词组的过程,每次搜索的实收需要搜索所有文档,每个文档i比较搜索条件和词组

Solr简介

反向索引:正向索引的逆向,建立词组和文档的映射关系。通过找到词组就能找到内容

Solr简介

Solr搜索原理

Solr能够提升检索效率,是因为分词和索引(反向索引)

分词:怼搜索条件/存储内容进行分词,分成日常所使用的词语

索引:存储在solr中内容按照程序员要求建立索引,如果要求建立索引,会把存储内容中关键字存储索引

Solr简介

Solr数据存储说明

Solr简介

Solr单机安装

使用git下载7.2版本solr

git clone https://github.com/apache/lucene-solr.git

进入solr目录

cd solr

修改启动参数

cd bin
vim solr.in.sh
SOLR_ULIMIT_CHECKS=false

之所以修改这个参数,是因为启动的时候有以下报错

Solr简介

启动solr

./solr start

如果是root账号,会有以下警告

Solr简介

加上force参数

./solr start -force

就像vs code,root账户需要参数 --user-data-dir

可视化管理界面

Solr简介

新建核心

Solr安装完成后默认没有核心,需要手动配置

在solr/server/solr下新建文件夹,并给定配置文件,否则无法建立

mkdir testcore

把configsets里面包含的所有配置文件都拷贝到testcore下面

cp -r configsets/_default/conf/ testcore/

填写core信息

Solr简介

分词Analysis

在solr可视化管理界面中,有一个Analysis

Solr简介

ik-analyzer

ik-analyzer是一个中文分词工具包

solr的ik-analyzer官方地址:https://github.com/magese/ik-analyzer-solr#%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E

下载对应的jar包,jar包地址:https://search.maven.org/remotecontent?filepath=com/github/magese/ik-analyzer/8.3.1/ik-analyzer-8.3.1.jar

下载到solr下的webapp/WEB-INF/lib目录中

cd solr/server/solr-webapp/webapp/WEB-INF/lib

然后是使用wget命令

wget https://search.maven.org/remotecontent?filepath=com/github/magese/ik-analyzer/8.3.1/ik-analyzer-8.3.1.jar

修改配置文件

vim solr/server/solr/testcore/conf/managed-schema

vim排版,gg=G

添加下面内容

<field name="myfield" type="text_ik" indexed="true" stored="true" />
    <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>

重启

cd solr/bin
./solr stop -all
./solr start -force

Managed-schema详解

<fieldType>

表示定义一个属性类型,在Solr中属性类型都是自定义的

例如name="text_ik"为自定义类型,当某个属性text_ik时,IK Analyzer才能生效

<field/>

表示向Document中添加一个属性

常用属性

  • name,属性名
  • type,属性类型
  • indexed,是否建立索引
  • stored,该属性是否必须,默认id是必须
  • multiValued,如果为true,复合属性,包含多个属性,常用多个列作为搜索条件时,
  • 把这些列定义成一个新的复合属性,通过搜索一个复合属性实现搜索多个列
  • 当设置为true时与<copyField source="" dest=""/>结合使用

<uniqueKey>

唯一主键,solr中默认定义id属性为唯一主键,ID的值不允许重复

<dynamicField>

名称中允许*进行通配,代表满足特定名称要求的一组属性

例如

  • test_*

Dataimport

可以使用solr自带的dataimport功能把数据库中数据快速导入到solr中

必须保证managed-schema和数据库中的表的列对应

修改配置文件

修改solrconfig.xml,添加下面内容

<!-- 配置数据导入的处理器 -->
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
    <lst name="defaults">
        <!-- 加载data-config.xml -->
        <str name="config">data-config.xml</str>
    </lst>
</requestHandler>

新建data-config.xml

和solrconfig.xml同一目录下新建data-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<dataConfig>
    <dataSource type="JdbcDataSource"
        driver="com.mysql.jdbc.Driver"
        url="jdbc:mysql://192.168.51.241:3306/maven"
        user="root"
        password="root"/>
    <document> 
        <entity name="product" query="SELECT id,name,price from product">
            <field column="id" name="id"/>
            <field column="name" name="name"/>
            <field column="price" name="price"/>
         </entity>
    </document>
</datraConfig>

添加三个jar

  • solr-dataimporthandler
  • solr-dataimporthandler-extras
  • mysql-connector

重启solr,使用可视化界面进行数据导入

菜单项目Documents使用办法

新增/修改

<doc>
<field name="id">8</field>
<field name="name">test</field>
<field name="price">98</field>
</doc>

删除

根据主键删除

<delete>
    <id>8</id>
</delete>
<commit/>

条件删除

<delete>
    <query>*:*</query>
</delete>

使用solrJ操作Solr

SolrJ是Solr提供的Java客户端API

添加SolrJ依赖,官方地址:https://mvnrepository.com/artifact/org.apache.solr/solr-solrj

<!-- https://mvnrepository.com/artifact/org.apache.solr/solr-solrj -->
<dependency>
    <groupId>org.apache.solr</groupId>
    <artifactId>solr-solrj</artifactId>
    <version>7.7.2</version>
</dependency>

新增/修改实现

String url = "http://192.168.93.10:8983/solr/testcore";
HttpSolrClient solrClient = new HttpSolrClient.Builder(url).build();
SoluInputDocument inputDocument = new SolrInputDocument();
inputDocument.addField("id", "3");
inputDocument.addField("myField", "myfield3");
solrClient.add(inputDocument);
solrClient.commit();

添加测试

public classs SolrTest{
    @Test
    public void testAddAndUpdate(){
        String url = "http://192.168.93.10:8983/solr/testcore";
        HttpSolrClient httpSolrClient = null; 
        try{
            HttpSolrClient httpSolrClient = new HttpSolrClient.Builder(url).build();  
            SoluInputDocument inputDocument = new SolrInputDocument();
            inputDocument.addField("id", "3");
            inputDocument.addField("name", "昨天最热手机");
            inputDocument.addField("price", "3999");
            solrClient.add(inputDocument);
            solrClient.commit();
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            httpSolrClient.close();
        }
    }
}

删除实现

String url = "http://192.168.93.10:8983/solr/testcore";
HttpSolrClient solrClient = new HttpSolrClient.Builder(url).build();
solrClient().commit();

删除测试

public classs testDelete() throws Exception{
    @Test
    public void testAddAndUpdate(){
        String url = "http://192.168.93.10:8983/solr/testcore";
        HttpSolrClient httpSolrClient = null; 
        try{
            HttpSolrClient httpSolrClient = new HttpSolrClient.Builder(url).build();  
            HttpSolrClient.deleteById("5");
            solrClient.commit();
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            httpSolrClient.close();
        }
    }
}

查询,排序,分页, 高亮

public classs testQuery() throws Exception{
    @Test
    public void testAddAndUpdate(){
        String url = "http://192.168.93.10:8983/solr/testcore";
        HttpSolrClient httpSolrClient = null; 
        try{
            HttpSolrClient httpSolrClient = new HttpSolrClient.Builder(url).build();  
            SolrQuery params = new SolrQuery();
            params.setQuery("name:丰富的");
            // 排序
            params.setSort("price", SolrQuery.ORDER.desc);
            // 分页
            params.setStart(0);
            params.setRows(1);
            // 高亮
            params.setHighlight(true);
            params.setHighlightField(“name");
            params.setHighlightSimplePre("<span>");
            QueryResponse response = solrClient.query(params);
            SolrDocumentList documents = response.getResults();
            System.out.println("总条数:" + documents.getNumFound());
            for(SolrDocument doc : documents){
                System.out.println(doc.get("id"));
                System.out.println(doc.get("name"));
                System.out.println(doc.get("price"));
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            httpSolrClient.close();
        }
    }
}

Spring Data for Apache Solr

Solr简介

 

添加依赖,官方地址:https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

添加依赖,官方地址:https://mvnrepository.com/artifact/org.springframework.data/spring-data-solr

<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-solr -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-solr</artifactId>
</dependency>

启动类

@SpringBootApplication
public class SolrApplication{
    public static void main(String[] args){
        SpringApplication.run(SolrApplication.class, args);
    }    
}

SpringDataSolrTest

添加一个

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SolrApplication.class)
public class SpringDataSolrTest{
    @Autowired
    private SolrTemplate solrTemplate;
    
    @Test
    public void testInsert(){
        SolrInputDocument document = new SolrInputDocument();
        document.addField("id", "7");
        document.addField("name", "phone");
        document.addField("price", 2888);
        solrTemplate.saveDocument("testcore", document);
        solrTemplate.commit("testcore");
    }
}

Product

public class Product{
    @Field
    private String id;
    @Field
    private String name;
    @Field
    private Double price;
    // getter setter
}

添加多个

testInsert2

@Test
public void testInsert2(){
    Product product = new Product();
    product.setId("8");
    product.setName("phone");
    product.setPrice(2847.1);
  
    Product product1 = new Product();
    product1.setId("9");
    product1.setName("phone1");
    product1.setPrice(2857.1);

    List<Product> list = new ArrayList<>();
    list.add(product);
    list.add(product1);

    solrTemplate.saveBeans("testcore", list);
    solrTemplate.commit("testcore");
}

编写配置文件

spring:
    data:
        solr:
            host: http://192.168.93.10:8983/solr
            # zk-host: 192.168.9.132:2181, 192.168.9.132:2182, 192.168.9.132:2183

修改

@Test
public void testUpdate(){
    SolrInputDocument document = new SolrInputDocument();
    document.addField("id", "7");
    document.addField("name", "phone123");
    document.addField("price", 12888);
    solrTemplate.saveDocument("testcore", document);
    solrTemplate.commit("testcore");
}

删除

@Test
public void testDelete(){
    solrTemplate.deleteByIds("testcore", 7);
    solrTemplate.commit("testcore");
}

查询

@Test
public void testQuery(){
    SimpleQuery query = new SimpleQuery();
    Criteria c = new Criteria("");
    criteria.is("phone");

    simpleQuery.addCriteria(criteria);

    ScoredPage<Product> testcore = solrTemplate.queryForPage("testcore", simpleQuery, Product.class);
    System.out.println(testcore.getContent());
     
}

 

上一篇:android开发两种退出程序方式(killProcess,System.exit)


下一篇:CVE-2019-17558漏洞复现