gacvd 发表于 2017-12-18 17:49:01

Solr快速入门

1. 什么是Solr
  Solr是基于lucene的全文检索服务器。
  不同于lucene工具包,solr是一个web应用,运行在servlet容器,屏蔽了底层细节,并对外提供服务。
  点我lucene快速入门
  Solr创建及维护索引:
  solr客户端向solr服务端发送POST请求,请求内容是包含Field等信息的一个xml文档。通过该文档,solr实现对索引的维护(增删改)。
  Solr的搜索:
  solr客户端向solr服务端发送GET请求,solr服务器返回一个xml文档。
  作为一个web应用,我们更多的工作不是编码而是配置。

2. Solr的安装与配置
  解压solr压缩文件,可以看到下面几个目录
  bin  : 存放solr命令
  contrib: solr增强功能
  dist   : solr编译后产生的war包和依赖包
  exapmle: solr的示例,其中,example/solr->solrhome, example/solr/collection1->solrcore
  slorhome是solr服务运行的主目录,一个solrhome里包含多个solrcore。
  solrcore存放了solr实例运行时需要的配置文件和索引数据,每个solrcore都可以单独提供服务,多个solrcore之间没有关系。
  不同的业务模块可以使用不同的solrcore来提供服务;建立solr集群的时候,必须配置多个solrcore。
  `solrcore`/conf->配置文件
  `solrcore`/data->solr的数据,包含索引文件和log
  `solrcore`/core.properties->本solrcore对外的名字
  安装配置步骤:
  1. 解压war包至servlet容器,删除war包
  2. 添加日志:
  example/lib/ext复制到solr的WEB-INF/lib下
  example/resources/log4j.properties复制到WEB-INF/classes下
  3. 添加分词器:
  分词器的jar包复制到solr的WEB-INF/lib下
  分词器的字典,停止词,配置文件复制到WEB-INF/classes下
  记得在后面配置分词器的fieldType
  4. 复制example下面的solrhome(含solrcore),至自定义目录下。如果需要,复制example下面的dist和contrib,至自定义目录下
  5. 修改Web.xml的<env-entry>,设置solrhome的位置
  6. 配置`solrcore`/conf/solrconfig.xml
  1)lib标签。如果需要,指定相关增强功能包的位置。其中solr.install.dir表示solrcore的位置,作相应修改("../"部分)
  2)datadir标签。指定data的位置,其中solr.data.dir表示`solrcore`/data,不用修改
  3)requestHandler标签。设置请求url和服务器索引维护(update),搜索(search)行为之间的对应关系。后面使用dataimport插件时需要设置。
  

<requestHandler name="/select">  <!-- 默认参数值,可以在请求URL中覆盖-->
  <lst name="defaults">
  <str name="echoParams">explicit</str>
  <int name="rows">10</int> <!--默认显示数量-->
  <str name="wt">json</str> <!--默认显示格式-->
  <str name="df">text</str> <!--默认搜索字段-->
  </lst>
  
</requestHandler>
  

  7. 配置`solrcore`/conf/schema.xml
  详解:
  

<!-- name:field的名称, 使用field必备; type:见下方fieldType,决定了是否分词; indexed:是否索引; stored:是否存储; required:该field是否必需;  multiValued: 是否存储多个值, 比如商品图片地址
-->  
<!-- 索引数据库中根据需要索引字段建立各field -->
  
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
  

  
<!-- 动态field, 用通配符指定field名称 -->
  
<dynamicField name="*_i"type="int" indexed="true" stored="true"/>
  

  
<!-- 唯一键, 用作id的field. 该field必须已经定义且required属性为true, schema中有且仅有一个uniqueKey-->
  
<uniqueKey>id</uniqueKey>
  

  
<!-- 复制域, source:被复制的field; dest:复制到的field. 两个field必须已经定义且dest的multiValued属性为true -->
  
<!-- 将多个域的信息复制到一个域里面, 目的: 方便组合查找 -->
  
<copyField source="cat" dest="text"/>
  

  
<!-- 域的类型,自定义分词器需要配置 >  
<fieldType name="text_general" positionIncrementGap="100">
  <analyzer type="index"> <!--建立索引时设置-->
  <tokenizer/> <!-- 建立索引时的分词器, 和搜索时分词器须相同 -->
  <filter ignoreCase="true" words="stopwords.txt" /> <!--停止词过滤器-->
  <filter/> <!--大写转小写过滤器-->
  </analyzer>
  <analyzer type="query"><!--搜索时设置, 与索引时设置基本一致, 可以只设置一个 -->
  <tokenizer/><!-- 搜索时的分词器, 和索引分词器须相同 -->
  <filter ignoreCase="true" words="stopwords.txt" />
  <filter synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
  <filter/>
  </analyzer>
  
</fieldType>
  

  添加dataimport插件
  dataimport插件实现将sql语句的查询结果批量导入到solr索引库中, 当然该功能也可以通过下面的SolrJ实现
  solr管理界面dataimport默认不可用, 以下步骤可开启:
  1.添加`solrcore`/conf/solrconfig.xml的lib标签, 指定dist/solr-dataimporthandler
  2.复制mysql数据库驱动包至contrib/db/lib下, 添加lib标签
  3.添加`solrcore`/conf/solrconfig.xml的requestHandler标签,>  4.建立data-config.xml文件



3. 通过SolrJ访问Solr
  维护索引:
  

public>

  @Test
public void createAndUpdateIndex() throws Exception {// 创建Document对象  SolrInputDocument doc = new SolrInputDocument();
  // field要求已经在solar服务器的配置文件中定义
  doc.addField("id", "testId");
  doc.addField("name", "testName");
  // 创建HttpSolrServer
  HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
  // 根据唯一键查找, 没有则创建, 有则修改
  
      server.add(doc);
  // 提交
  
      server.commit();
  }
  

  @Test
  public void deleteIndex() throws Exception {
  HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
  // 根据ID删除
  server.deleteById("c001");
  // 根据条件删除
  server.deleteByQuery("id:c001");
  // 删除全部(慎用)
  server.deleteByQuery("*:*");
  // 提交
  
      server.commit();
  }
  
}
  

  搜索:
  

public>

  @Test
public void searchSimple() throws Exception {  HttpSolrServer server
= new HttpSolrServer("http://localhost:8080/solr");// 创建SolrQuery对象  SolrQuery query = new SolrQuery();
  // 查询条件
  query.setQuery("product_name:玩具");
  // 执行查询并接收响应
  QueryResponse response = server.query(query);
  // 拿到结果
  SolrDocumentList queryResults = response.getResults();
  // 匹配结果总数
  long count = queryResults.getNumFound();
  System.out.println("结果总数:" + count);
  for (SolrDocument doc : queryResults) {
  System.out.println(doc.get("id"));
  System.out.println(doc.get("product_name"));
  System.out.println(doc.get("product_catalog"));
  System.out.println(doc.get("product_price"));
  System.out.println(doc.get("product_picture"));
  }
  }
  

  @Test
  public void searchComplicate() throws Exception {
  SolrQuery query = new SolrQuery();
  query.set("q", "product_name:玩具");
  

  // 设置过滤条件, 可添加多个
  query.addFilterQuery("product_price:");
  // 设置排序
  query.setSort("product_price", ORDER.asc);
  // 设置结果分页
  query.setStart(0);
  query.setRows(10);
  // 设置结果显示的Field域集合
  query.setFields("id,product_name,product_price");
  // 设置默认搜索域, 查询语句中不需要"product_keywords:"了
  query.set("df", "product_keywords");
  // 设置某field高亮显示
  query.setHighlight(true);
  query.addHighlightField("product_name");
  query.setHighlightSimplePre("<font style=\"color:red\">");
  query.setHighlightSimplePost("</font>");
  HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");
  QueryResponse response = server.query(query);
  // 得到结果
  SolrDocumentList queryResults = response.getResults();
  long count = queryResults.getNumFound();
  System.out.println("匹配结果总数:" + count);
  // 得到被封装的高亮结果, 类似: 普通字段<font>高亮字段</font>普通字段
  Map<String, Map<String, List<String>>> hlResults = response.getHighlighting();
  for (SolrDocument doc : queryResults) {
  System.out.println(doc.get("id"));
  // 解析被封装的带高亮显示的结果. 对可能的高亮field分别处理
  List<String> hlLists = hlResults.get(doc.get("id")).get("product_name");
  if (hlLists != null)
  System.out.println("高亮显示商品名:" + hlLists.get(0));
  else {
  System.out.println("正常显示商品名:" + doc.get("product_name"));
  }
  System.out.println(doc.get("product_price"));
  }
  }
  
}
  


4. SolrCloud的搭建与访问
  Solr集群需要用到多个solr与多个zookeeper
  这里搭一个如下的简单架构作为例子

  zookeeper在这个集群的作用:
  1. 集群管理. 负责solr的主从关系, 负载均衡, 作为外界访问集群的入口. 为了保证高可用, zookeeper自身也必须是集群. 为使选举和投票有效, zookeeper至少需要三个节点.
  2.配置文件管理. 各solr配置文件相同, 将配置文件上传给zookeeper统一管理, 每个solr节点都到zookeeper上取配置.
  如果在一台主机上搭建集群, 注意避免端口冲突.

4.1 搭建zookeeper集群
  1)在zookeeper01目录下创建一个data文件夹。
  2)在data目录下创建一个myid的文件
  3)Myid的内容为1(zookeeper02对应“2”,zookeeper03对应“3”)
  4)进入conf文件, 复制zoo_sample.cfg模板文件创建zoo.cfg
  5)修改zoo.cfg
  把dataDir属性指定为刚创建的data文件夹
  指定clientPort, 这是外界访问zookeeper01的端口
  添加如下内容:
  server.1=`zookeeper01的ip`:`port2`:`port3`
  server.2=`zookeeper02的ip`:`port2`:`port3`
  server.3=`zookeeper03的ip`:`port2`:`port3`
  两个端口号分别是zookeeper间相互通信, 进行投票和选举的端口
  6)zookeeper02 03以此类推
  7)启动zookeeper. 使用zookeeper的bin目录下的zkServer.sh
  启动:./zkServer.sh start
  关闭:./zkServer.sh stop
  查看服务状态:./zkServer.sh status

4.2 搭建solr集群
  1)需要准备4台tomcat与4个solr实例
  2)创建solrhome, 修改web.xml关联solrhome等类似单机solr
  3)修改`solrhome`/solr.xml. 将solrCloud下的host, hostPort修改为所在的web容器访问地址与端口号
  4)使用solr-4.10.3/example/scripts/cloud-scripts/zkcli.sh命令将某台的`solrcore`/conf目录上传到zookeeper集群
  

./zkcli.sh -zkhost `zookeeper01的ip`:`port1`,zookeeper02的ip`:`port1`,zookeeper03的ip`:`port1` -cmd upconfig -confdir `solrcore`/conf -confname myconf  

  查看是否上传成功, 使用zookeeper的zkCli.sh命令
  5)通知solr实例zookeeper的位置。修改tomcat的catalina.sh添加
  

JAVA_OPTS="-DzkHost=`zookeeper01的ip`:`port1`,zookeeper02的ip`:`port1`,zookeeper03的ip`:`port1`"  

  6)启动solr实例, 访问如下url进行分片, 分为2片, 每片一主一从
  分片, 创建solrcore collection2:
  http://某solr的ip:port/solr/admin/collections?action=CREATE&name=collection2&numShards=2&replicationFactor=2
  可以删除不用的solrcore collection1
  http://某solr的ip:port/solr/admin/collections?action=DELETE&name=collection1

4.3 使用SolrJ访问集群
  

public>@Testpublic void createAndUpdateIndex() throws Exception {  

  SolrInputDocument document
= new SolrInputDocument();  document.addField(
"id", "testId");  document.addField(
"item_title", "testName");  

// 创建一个SolrServer对象, zkHost地址为三个zookeeper地址  CloudSolrServer solrServer = new CloudSolrServer("192.168.25.154:2181,192.168.25.154:2182,192.168.25.154:2183");
  // 设置使用的solrcore(分片策略)
  solrServer.setDefaultCollection("collection2");
  solrServer.add(document);
  solrServer.commit();
  }
  
}
  

  可以看出除了获取solrServer, 使用上和单机版没有任何区别. 集群对客户端来说的封闭的.
页: [1]
查看完整版本: Solr快速入门