Solr教程

前言

至于为什么要用solr5.5,因为最新的6.10,没有中文的分词器支持,这里使用的是ik分词器,刚好支持到5.5

ik分词器下载地址 :https://github.com/EugenePig/ik-analyzer-solr5  , 下载完之后使用maven命令, mvn package 即可生成jar文件,或者下载我编译好的 http://pan.baidu.com/s/1o7P0846

solr5.5下载地址: http://apache.fayea.com/lucene/solr/5.5.2/

tomcat8下载,下载地址就不说了

 

 

一:安装配置

下载完成之后,解压solr文件,解压tomcat

 1.1 在tomcat安装solr,并且建立solrCore

  1. 把solr5.5目录下的server/solr-webapp/webapp 重命名为solr,并且放置到tomcat/webapp的目录下。 
  2. 打开tomcat/webapp/solr/WEB-INF/web.xml
  3. 新建一个文件夹,不要中文目录,用来做solrHome,也就是solrCore的实例存放位置
  4. 在tomcat/webapp/solr/WEB-INF/web.xml中配置solr的地址
  5. 在tomcat/webapp/solr/WEB-INF/文件夹中,建立classes目录

  6. 把solr5.5/server/resource/log4j.properties 复制到上一步建立的classes目录中
  7. 把solr5.5/server/lib/ext/目录下的所有jar文件复制到tomcat/webapp/solr/WEB-INF/lib/中,这是一些日志用的jar包,不然启动报错。
  8. 这个时候,可以输入http://127.0.0.1:8080/solr/admin.html来访问到solr的控制界面了。
  9. 接下来就是创建solrCore。
  10. 目前solrHome目录是空的,我们创建一个空文件夹core1,这个就是我们的一个实例,然后把solr5.5/server/solr/configsets/sample_techproducts_configs/conf/ 这个文件复制到solrHome/core1中。
  11. 把solr5.5/server/solr/solr.xml复制到solrHome目录下。
  12. 在solr的管理控制台界面,添加一个core1
  13.  

  14. 这下就创建成功了一个实例core1,yge 请注意我打码的部分,需要先执行第11步操作,否则的话,会无法创建solr core,也就是会有错误信息,这是solr的一个bug,但是至今没有修复。

 

1.2 安装ik中文分词器

  1. 准备好ik分词器的jar包,可以自己编译,也可以下载我生成的。然后把它复制到tomcat/webapp/solr/WEB-INF/lib里面。(千万不要复制到tomcat/lib中,这样会找不到lucene的类)
  2. 打开solrHome/core1/conf/managed-schema文件,在最下方,追加如下配置
  3. 复制代码
        <fieldType name="text_ik" class="solr.TextField"> <analyzer type="index" useSmart="false" class="org.wltea.analyzer.lucene.IKAnalyzer" /> <analyzer type="query" useSmart="true" class="org.wltea.analyzer.lucene.IKAnalyzer" /> </fieldType>
    复制代码

     

  4. 启动tomcat,即可看到text_ik分词
  5.  

 

1.3 插入的文档必须与域相匹配

域,我个人也称它为字段,它在solr中有特定的含义,就类似数据库中表的列一样,规范着写入的数据,我们先来做个例子。

可以看到,我这次插入的文档,有id,title当然,在solr中,每一条记录都必须有着一个唯一的id,它就类似数据库中的主键,不可重复。这条记录的插入是成功的。

但是,如果我把title改成title1,这就与定义的字段不一样了,就会报错,如下图所示

可以看到,这里提示,未知的字段 title1.

 

1.4 域的定义 field

先拿出一条配置来看一下

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

 认识一下这些属性

  name:域名

  type:域的类型,必须匹配类型,不然会报错

  indexed:是否要作索引

  stored:是否要存储

  required:是否必填,一般只有id才会设置

  multiValued:是否有多个值,如果设置为多值,里面的值就采用数组的方式来存储,比如商品图片地址(大图,中图,小图等)

 

1.5 配置动态域 dynamicField

同样的,也先拿出一条来看看

<dynamicField name="*_i"  type="string" indexed="true" stored="true" multiValued="true" />

何谓动态域呢?就是这个域的名称,是由表达式组成的,只要名称满足了这个 表达式,就可以用这个域

 同样的认识一下这些属性

  name:域的名称,该域的名称是通过一个表达式来指定的,只要符合这这个规则,就可以使用这个域。比如  aa_i,bb_i,13_i等等,只要满足这个表达式皆可

  type:对应的值类型,相应的值必须满足这个类型,不然就会报错

  indexed:是否要索引

  stored:是否要存储

  ...其它的属性与普通的域一至

 

 

 

 

1.6 主键域 uniqueKey

给出一条配置

 <uniqueKey>id</uniqueKey>

指定一个唯一的主键,每一个文档中,都应该有一个唯一的主键,这个值不要随便改

 

 

 

1.7 复制域 copyField

给出一条配置

<copyField source="cat" dest="text"/>

说明一下相应的属性

  source:源域

  dest:目标域

复制域,将源域的内容复制到目标域中

注意:目标域必须是允许多值的,如下,nultiValued必须为true,因为可能多个源域对应一个目标域,所以它需要以数组来存储

<field name="text" type="string" indexed="true" stored="true" multiValued="true"/>

 

 

 

 

1.8 域的类型 fieldType

同样的给出一段配置,这段稍微有点复杂

复制代码
    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" /> <!-- in this example, we will only use synonyms at query time <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/> --> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" /> <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> </fieldType>
复制代码

给出相应属性的说明

  name:域的名称

  class:指定solr的类型

  analyzer:分词器的配置

    type: index(索引分词器),query(查询分词器)

    tokenizer:配置分词器

    filter:过滤器

 

 

 

 

1.9 业务字段的实际配置

经过上面的学习,差不多了解了一些常用的配置,如今我们用field来配置实际的业务字段,有属性如下

当然,中文分词还是要用的,因为我们在前面的  1.2  章节中,已经配置了一个fieldType的中文分词,所以我们现在一律用中文分词的域类型

 

主键的id就不需要配置了,默认已经把id配置为主键了,默认的配置如下

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

商品名称(需要分词,需要存储)

<field name="name" type="text_ik" indexed="true" stored="true" /> 

商品分类(不需要分词,需要存储)

<field name="catalog" type="int" indexed="false" stored="true" /> 

商品分类名称(需要分词,需要存储)

<field name="catalog_name" type="text_ik" indexed="true" stored="true" /> 

商品价格(不分词,需要存储)

<field name="price" type="double" indexed="false" stored="true" /> 

商品描述(需要分词,不需要存储)

<field name="description" type="text_ik" indexed="true" stored="false" /> 

商品图片(不需要分词,需要存储)

<field name="picture" type="string" indexed="false" stored="true" /> 

 

复制域的应用

前面我们了解了复制域,但是却不知道它的应用场景,现在我们结合实际情况来讲一下复制域

用户在搜索框搜索的时候,有可能输入的是商品名称,也有可能输入的是商品描述,也有可能输入的是一个商品类型,那么这些值的搜索,肯定在后台是对应一个域的,那么既然如此,我们就可以把这些域合并成一个,这样在后台只需要单独的对这一个域进行搜索就可以了

先定义一个目标域

<field name="keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/> 

复制域,把商品名称,商品描述,商品类型名称复制到上面的这个域中

<copyField source="name" dest="keywords"/> <copyField source="catalog_name" dest="keywords"/> <copyField source="description" dest="keywords"/>

 

 

1.10 dataimport 导入数据库数据

solr默认是没有开启dataimport这个功能的,所以我们要经过一点配置来开启它

  1. 首先找到solr5.5/dist/solr-dataimporthandler-5.5.2.jar,把这个文件复制到tomcat/webapp/solr/WEB-INF/lib/下,并且找到相应数据库的驱动包,也同样放到该目录。我这里用的是mysql的驱动包。
  2. 找到solr5.5/example/example-DIH/solr/db/conf/db-data-config.xml,把其复制到solrHome/core1/conf/下,并改名为data-config.xml.
  3. 找到solrHome/core1/conf/solrconfig.xml,并打开,在里面添加一段内容,如下
  4.   <requestHandler name="/dataimport" class="solr.DataImportHandler"> <lst name="defaults"> <str name="config">data-config.xml</str> </lst> </requestHandler>

     

  5. 打开并编辑data-config.xml,完整的配置文件如下
  6. 复制代码
     <dataConfig>
        <!-- 这是mysql的配置,学会jdbc的都应该看得懂 --> <dataSource driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/solr/useUnicode=true&characterEncoding=utf-8" user="root" password="密码"/> <document> <!-- name属性,就代表着一个文档,可以随便命名 --> <!-- query是一条sql,代表在数据库查找出来的数据 --> <entity name="product" query="select * from products"> <!-- 每一个field映射着数据库中列与文档中的域,column是数据库列,name是solr的域(必须是在managed-schema文件中配置过的域才行) --> <field column="pid" name="id"/> <field column="name" name="product_name"/> <field column="catalog" name="product_catalog"/> <field column="catalog_name" name="product_catalog_name"/> <field column="price" name="product_price"/> <field column="description" name="product_description"/> <field column="picture" name="product_picture"/> </entity> </document> </dataConfig>
    复制代码

     

  7. 重启tomcat,然后会看到如下页面
  8.  

  9. 点击蓝色的按钮,则开始导入,导入过程依据数量量的大小,需要的时间也不同,可以点击右边的Refresh status来刷新状态,可以查看当前导入了多少条。
  10. 导入成功如下
  11.  

 

 

 

 

二:solrj的使用

代码地址 https://github.com/zxj19951029/useSolrj

上面一章节已经讲完了solr的安装与配置,现在说一下使用solrj来维护solr的索引及操作,solrj就是一个java的客户端,是一个jar包的使用

首先引入MAVEN的依赖,solrj的版本号要对应solr的版本号

        <dependency>
            <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> <version>5.5.2</version> </dependency>

 

 

2.1 增加及修改

首先说明,在solr中,增加与修改都是一回事,当这个id不存在时,则是添加,当这个id存在时,则是修改

代码很好理解,直接给出

 

复制代码
    private String serverUrl = "http://192.168.1.4:8080/solr/core1";
    /**
     * 增加与修改<br>
     * 增加与修改其实是一回事,只要id不存在,则增加,如果id存在,则是修改
     * @throws IOException * @throws SolrServerException */ @Test public void upadteIndex() throws SolrServerException, IOException{ //已废弃的方法 //HttpSolrServer server = new HttpSolrServer("http://192.168.1.4:8080/solr/core1"); //创建 HttpSolrClient client = new HttpSolrClient(serverUrl); SolrInputDocument doc = new SolrInputDocument(); doc.addField("id", "zxj1"); doc.addField("product_name", "javaWEB技术"); doc.addField("product_catalog", "1"); doc.addField("product_catalog_name", "书籍"); doc.addField("product_price", "11"); doc.addField("product_description", "这是一本好书"); doc.addField("product_picture", "图片地址"); client.add(doc); client.commit(); client.close(); }
复制代码

 

 

 

2.2 删除索引

删除的代码也直接给出,看代码里面的注释就可以了

复制代码
    /**
     * 删除索引
     * @throws Exception
     */ @Test public void deleteIndex()throws Exception{ HttpSolrClient client = new HttpSolrClient(serverUrl); //1.删除一个 client.deleteById("zxj1"); //2.删除多个 List<String> ids = new ArrayList<>(); ids.add("1"); ids.add("2"); client.deleteById(ids); //3.根据查询条件删除数据,这里的条件只能有一个,不能以逗号相隔 client.deleteByQuery("id:zxj1"); //4.删除全部,删除不可恢复 client.deleteByQuery("*:*"); //一定要记得提交,否则不起作用  client.commit(); client.close(); }
复制代码

 

 

 

2.3 查询

查询稍微复杂一点,但是与solr管理界面的条件一致

这里先给出一些查询的说明,建议查看这篇文章,个人感觉还是不错的http://blog.csdn.net/gufengshanyin/article/details/21098879

  • q - 查询字符串,如果查询所有*:* (id:1)
  • fq - (filter query)过虑查询,过滤条件,基于查询出来的结果
  • fl - 指定返回那些字段内容,用逗号或空格分隔多个。
  • start - 分页开始
  • rows - 分页查询数据
  • sort - 排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 。示例:(score desc, price asc)表示先 “score” 降序, 再 “price” 升序,默认是相关性降序。
  • wt - (writer type)指定输出格式,可以有 xml, json, php, phps。
  • fl表示索引显示那些field( *表示所有field,如果想查询指定字段用逗号或空格隔开(如:Name,SKU,ShortDescription或Name SKU ShortDescription【注:字段是严格区分大小写的】))
  • q.op 表示q 中 查询语句的 各条件的逻辑操作 AND(与) OR(或)
  • hl 是否高亮 ,如hl=true
  • hl.fl 高亮field ,hl.fl=Name,SKU
  • hl.snippets :默认是1,这里设置为3个片段
  • hl.simple.pre 高亮前面的格式
  • hl.simple.post 高亮后面的格式
  • facet 是否启动统计
  • facet.field 统计field

1. “:” 指定字段查指定值,如返回所有值*:*
2. “?” 表示单个任意字符的通配
3. “*” 表示多个任意字符的通配(不能在检索的项开始使用*或者?符号)
4. “~” 表示模糊检索,如检索拼写类似于”roam”的项这样写:roam~将找到形如foam和roams的单词;roam~0.8,检索返回相似度在0.8以上的记录。
5. 邻近检索,如检索相隔10个单词的”apache”和”jakarta”,”jakarta apache”~10
6. “^” 控制相关度检索,如检索jakarta apache,同时希望去让”jakarta”的相关度更加好,那么在其后加上”^”符号和增量值,即jakarta^4 apache
7. 布尔操作符AND、||
8. 布尔操作符OR、&&
9. 布尔操作符NOT、!、- (排除操作符不能单独与项使用构成查询)
10. “+” 存在操作符,要求符号”+”后的项必须在文档相应的域中存在
11. ( ) 用于构成子查询
12. [] 包含范围检索,如检索某时间段记录,包含头尾,date:[200707 TO 200710]

 

给出基本的代码看一下,仅仅作为一个基本的查询,高级的查询,各位要自己结合文档

复制代码
package zxj.solrj;

import java.util.List;
import java.util.Map; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.junit.Test; /** * 搜索 * @author Administrator * */ public class IndexSearch { private String serverUrl = "http://192.168.1.4:8080/solr/core1"; @Test public void search()throws Exception{ HttpSolrClient client = new HttpSolrClient(serverUrl); //创建查询对象 SolrQuery query = new SolrQuery(); //q 查询字符串,如果查询所有*:* query.set("q", "product_name:小黄人"); //fq 过滤条件,过滤是基于查询结果中的过滤 query.set("fq", "product_catalog_name:幽默杂货"); //sort 排序,请注意,如果一个字段没有被索引,那么它是无法排序的 // query.set("sort", "product_price desc"); //start row 分页信息,与mysql的limit的两个参数一致效果 query.setStart(0); query.setRows(10); //fl 查询哪些结果出来,不写的话,就查询全部,所以我这里就不写了 // query.set("fl", ""); //df 默认搜索的域 query.set("df", "product_keywords"); //======高亮设置=== //开启高亮 query.setHighlight(true); //高亮域 query.addHighlightField("product_name"); //前缀 query.setHighlightSimplePre("<span style='color:red'>"); //后缀 query.setHighlightSimplePost("</span>"); //执行搜索 QueryResponse queryResponse = client.query(query); //搜索结果 SolrDocumentList results = queryResponse.getResults(); //查询出来的数量 long numFound = results.getNumFound(); System.out.println("总查询出:" + numFound + "条记录"); //遍历搜索记录 //获取高亮信息 Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting(); for (SolrDocument solrDocument : results) { System.out.println("商品id:" + solrDocument.get("id")); System.out.println("商品名称 :" + solrDocument.get("product_name")); System.out.println("商品分类:" + solrDocument.get("product_catalog")); System.out.println("商品分类名称:" + solrDocument.get("product_catalog_name")); System.out.println("商品价格:" + solrDocument.get("product_price")); System.out.println("商品描述:" + solrDocument.get("product_description")); System.out.println("商品图片:" + solrDocument.get("product_picture")); //输出高亮 Map<String, List<String>> map = highlighting.get(solrDocument.get("id")); List<String> list = map.get("product_name"); if(list != null && list.size() > 0){ System.out.println(list.get(0)); } } client.close(); } }
复制代码

注意:没有索引的域,是不能用作排序的

 

转载于:https://www.cnblogs.com/Taeyang/p/8205503.html

已标记关键词 清除标记
表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
1 概述 4 1.1 企业搜索引擎方案选型 4 1.2 Solr的特性 4 1.2.1 Solr使用Lucene并且进行了扩展 4 1.2.2 Schema(模式) 5 1.2.3 查询 5 1.2.4 核心 5 1.2.5 缓存 5 1.2.6 复制 6 1.2.7 管理接口 6 1.3 Solr服务原理 6 1.3.1 索引 6 1.3.2 搜索 7 1.4 源码结构 8 1.4.1 目录结构说明 8 1.4.2 Solr home说明 9 1.4.3 solr的各包的说明 10 1.5 版本说明 11 1.5.1 1.3版本 11 1.5.2 1.4版本 12 1.6 分布式和复制 Solr 架构 13 2 Solr的安装与配置 13 2.1 在Tomcat下Solr安装 13 2.1.1 安装准备 13 2.1.2 安装过程 14 2.1.3 验证安装 15 2.2 中文分词配置 15 2.2.1 mmseg4j 15 2.2.2 paoding 19 2.3 多核(MultiCore)配置 22 2.3.1 MultiCore的配置方法 22 2.3.2 为何使用多core ? 23 2.4 配置文件说明 23 2.4.1 schema.xml 24 2.4.2 solrconfig.xml 25 3 Solr的应用 29 3.1 SOLR应用概述 29 3.1.1 Solr的应用模式 29 3.1.2 SOLR的使用过程说明 30 3.2 一个简单的例子 30 3.2.1 Solr Schema 设计 30 3.2.2 构建索引 30 3.2.3 搜索测试 31 3.3 搜索引擎的规划设计 32 3.3.1 定义业务模型 32 3.3.2 定制索引服务 34 3.3.3 定制搜索服务 34 3.4 搜索引擎配置 34 3.4.1 Solr Schema 设计(如何定制索引的结构?) 34 3.5 如何进行索引操作? 36 3.5.1 基本索引操作 36 3.5.2 批量索引操作 37 3.6 如何进行搜索 39 3.6.1 搜索语法 39 3.6.2 排序 42 3.6.3 字段增加权重 42 3.6.4 Solr分词器、过滤器、分析器 42 3.6.5 Solr高亮使用 46 4 SolrJ的用法 46 4.1 搜索接口的调用实例 46 4.2 Solrj的使用说明 47 4.2.1 Adding Data to Solr 47 4.2.2 Directly adding POJOs to Solr 49 4.2.3 Reading Data from Solr 51 4.3 创建查询 51 4.4 使用 SolrJ 创建索引 52 4.5 Solrj包的结构说明 53 4.5.1 CommonsHttpSolrServer 53 4.5.2 Setting XMLResponseParser 53 4.5.3 Changing other Connection Settings 53 4.5.4 EmbeddedSolrServer 54 5 Solr的实际应用测试报告 54 5.1 线下压力测试报告 54 5.2 线上环境运行报告 54 6 solr性能调优 55 6.1 Schema Design Considerations 55 6.1.1 indexed fields 55 6.1.2 stored fields 55 6.2 Configuration Considerations 55 6.2.1 mergeFactor 55 6.2.2 mergeFactor Tradeoffs 56 6.3 Cache autoWarm Count Considerations 56 6.4 Cache hit rate(缓存命中率) 56 6.5 Explicit Warming of Sort Fields 56 6.6 Optimization Considerations 56 6.7 Updates and Commit Frequency Tradeoffs 56 6.8 Query Response Compression 57 6.9 Embedded vs HTTP Post 57 6.10 RAM Usage Considerations(内存方面的考虑) 57 6.10.1 OutOfMemoryErrors 57 6.10.2 Memory allocated to the Java VM 57 7 FAQ 58 7.1 出现乱码或者查不到结果的排查方法: 58
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页