zoukankan      html  css  js  c++  java
  • solr

    一. solr的启动方式

    1. start.jar启动

      cd  solr-4.10.4example
      java -jar start.jar
      java -Djetty.port=8980  -jar start.jar  #指定端口  --daemon 后台运行
      #####  java -jar --help 执行帮助命令  #####
      
    2. bin/solr执行

      不加参数有提示
      bin/solr   start   -p  8983     # 开启指定端口的solr
      bin/solr   stop   -p  8983      # 关闭指定端口的solr
      
    3. tomcat启动solr
      (1)建立一个solr的运行目录
      例如:D:solr-tomcat
      将下载的solr-4.10.4中的solr-4.10.4example目录下的solr文件夹拷贝到D:solr-tomcat目录下
      (2)建立JNDI文件
      在tomcat的confCatalinalocalhost目录下建立文件solr.xml

      <Context path="/solr" docBase="D:apache-tomcat-8.0.15solr.war"> 
          <Environment name="solr/home" type="java.lang.String" value="D:solr-tomcatsolr" override="true"/> 
      </Context>
      

      (3)部署solr.war包
      把solr-4.10.4中dist目录中的solr-4.10.4.war包拷贝到tomcat的根目录下,名字改为solr.war

      (4)配置日志
      如果不配置的话,启动会报错,无法访问solr平台,查看localhost.2015-01-01.log日志。
      把solr-4.10.4examplelibext目录下的jar包都拷贝到tomcat的lib目录下即可。
      访问http://localhost:8080/solr/

    二. solr的目录配置

    1. example目录是solr项目的根目录
      若根目录改名, 启动方式如下:
      a) bin/solr -s 没目录名
      b) cd 指定目录 & java -jar start.jar

    2. example/solr目录 : (start.jar同级目录下的solr目录 )
      若改变索引库目录, 启动方式如下:
      a) java -Dsolr.solr.home=(对于start.jar的相对路径) -jar start.jar
      b) solr start -s (对于start.jar的相对路径)

    3. example/solr-webapp 目录
      solr项目的部署位置 , solr启动后把 examplewebappssolr.war拷贝到 examplesolr-webappwebapp下面

    三. scchemal文件

    1. field : 静态字段
      (1)name:字段名
      (2)type:之前定义过的各种FieldType
      (3)indexed:是否被索引
      (4)stored:是否被存储(如果不需要存储相应字段值,尽量设为false)
      (5)multiValued:是否有多个值(对可能存在多值的字段尽量设置为true,避免建索引时抛出错误)

      <field name="_version_" type="long" indexed="true" stored="true"/>
      
    2. Dynamic Fields : 动态字段
      动态字段建立的索引存储规则 , 所有匹配到的字段名都会按照这种方式建立索引

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

    匹配规则 :
    (1)如果一个field的名字没有匹配到,那么就会用动态field试图匹配定义的各种模式。
    (2)""只能出现在模式的最前和最后
    (3)较长的模式会被先去做匹配 :
    (4)<dynamicField name="
    _ss>比<dynamicField name="*_s>先匹配
    (5)如果2个模式同时匹配上,最先定义的优先
    3. copyField : 拷贝字段
    (1)将多个field的数据放在一起同时搜索,提供速度
    (2)将一个field的数据拷贝到另一个,可以用2种不同的方式来建立索引。

    ```xml
    <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>  <!--组合字段要声明成multiValued="true"-->
    <copyField source="cat" dest="text"/>   <!--cat name text是上文建立好的静态字段-->
    <copyField source="name" dest="text"/>
    ```
    

    应用场景 :
    比如现在要查询包涵"Java"的博客, 那么你肯定要查内容,标题是否包含Java,但是solr不能像SQL那样,
    where tittle like '%Java%' or content like '%Java%'. 这个时候copyField就派上用场了,
    定义一个新字段,将title和content 复制到这个新字段,索引的时候,直接从这个新字段查询,这样就达到目地了。

    1. fieldType : 字段类型
      <fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true" />
      <!--声明字段类型 , 供<field>引用-->
      

    【注】: solr中1个core是一个数据库 , 称作为collection。每一个collection包含一个schemal.xml , 用于描述索引结构

    五. 查询语法

    1. id:aaa [AND][OR] name:lj : 交集并集
    2. price:[0 TO 93] : 范围查询 []闭区间,{}开区间
    3. filterquery : 把第一次查询结果进行缓存
    4. sort : 类似于mysql的order by price desc
    5. start,rows : 相当于limit关键字
    6. fl : 指定查询的字段
    7. df : default field 默认查询字段
    8. facet.query : 相当于group by price:[0 TO 100]
      ROW.QUERY.PARAMETER : facet.query = price:[0 TO 100] && price:{100 TO 100]
    9. facet.field : 分组字段 // name
    10. facet.prefix : 字段值前缀 // a
    11. Request-Handler : 配置的解析引擎
      /select :
      /spell : 实现拼写检查

    六. 分词器

    1. 分词器 : 把一段文本按照一定规则进行切分

       <fieldType name="text_nl" class="solr.TextField" positionIncrementGap="100">
          <analyzer> 
              <tokenizer class="solr.StandardTokenizerFactory"/>
              <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_nl.txt" format="snowball" />
          </analyzer>
      </fieldType>
      
    2. 分词器的一般工作流程:
      (1)切分关键词
      (2)去除停用词
      (3)对于英文单词,把所有字母转为小写(搜索时不区分大小写)

    七. IKAnalyzer整合solr

    1. 整合 : 通过页面上的Analyse测试效果
      (1)下载IK工具包
      (2)上传服务器,并解压,使用unzip命令
      (3)IKAnalyzer2012FF_u1.jar 拷贝到solr-web项目的lib目录下面

      cp IKAnalyzer2012FF_u1.jar solr-4.10.4/example/solr-webapp/webapp/WEB-INF/lib/
      

    (4)IKAnalyzer.cfg.xml和stopword.dic 拷贝到solr-web项目的类路径下
    注意:项目的类路径是指WEB-INF下面的classes目录,但是这个目录现在是不存在的,所以需要手工创建。
    shell cp IKAnalyzer.cfg.xml solr-4.10.4/example/solr-webapp/webapp/WEB-INF/classes/ cp stopword.dic solr-4.10.4/example/solr-webapp/webapp/WEB-INF/classes/
    (5)修改schem.xml文件(solr-4.10.4/example/solr/collection1/conf/schema.xml)
    xml <!--配置IK分词器--> <fieldType name="text_ik" class="solr.TextField"> <!--索引时候的分词器--> <analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/> <!--查询时候的分词器--> <analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/> </fieldType>
    (6)重启solr即可

    1. 自定义词库
      (1)首先要有一个自定义字典,my.dic
      自定义字典中的一行代表一个词语
      注意:这个文件的编码必须是utf-8 without bom
      (2)把这个dic文件上传到solrweb项目的类路径下
      (3)修改ik的配置文件(IKAnalyzer.cfg.xml)
      <properties>
          <comment>IK Analyzer 扩展配置</comment>
          <!--用户可以在这里配置自己的扩展字典 -->
          <entry key="ext_dict">my.dic;</entry>
          <!--用户可以在这里配置自己的扩展停止词字典-->
          <entry key="ext_stopwords">stopword.dic;</entry>
      </properties>
      

    (4)重启solr
    (5)(可选)添加多个自定义字典

    ```xml
    <entry key="ext_dict">my.dic;my1.dic;</entry>
    ```
    

    八. solr多core

    1. 界面操作
      core admin --> add core 界面上的unload可以让一个core下线,下线就是重命名core.properties为core.properties.unload
    2. 直接操作
      (1)cp example/solr/collection1 crxy
      (2)修改core.properties文件 : name=crxy

    九. SolrJ

    1. 实体类注解
      public class Article {  
            
          @Field     // 进行添加索引的属性加@Field注解  
          private String id;  
          @Field  
          private String title;  
            
          @Field  
          private String describe;  
            
          private String content;  
          @Field  
          private String author;  
          public String getId() {  
              return id;  
          }  
          public void setId(String id) {  
              this.id = id;  
          }  
          public String getTitle() {  
              return title;  
          }  
          public void setTitle(String title) {  
              this.title = title;  
          }  
          public String getContent() {  
              return content;  
          }  
          public void setContent(String content) {  
              this.content = content;  
          }  
          public String getAuthor() {  
              return author;  
          }  
          public void setAuthor(String author) {  
              this.author = author;  
          }  
          public String getDescribe() {  
              return describe;  
          }  
          public void setDescribe(String describe) {  
              this.describe = describe;  
          }  
            
      }  
      
    2. SolrUtil工具类
      public class SolrUtil {  
          static final Logger logger = LoggerFactory.getLogger(SolrUtil.class);  
          // shard分片下,无论连哪个地址都会查询所有shard  
          private static final String SOLR_URL = "http://192.168.182.130:7574/solr/collection1"; 
          private static HttpSolrServer server = null;  
          static{  
              try {  
                  server = new HttpSolrServer(SOLR_URL);  
                  server.setAllowCompression(true);  
                  server.setConnectionTimeout(10000);  
                  server.setDefaultMaxConnectionsPerHost(100);  
                  server.setMaxTotalConnections(100);  
              } catch (Exception e) {  
                  logger.error("请检查tomcat服务器或端口是否开启!{}",e);  
                  e.printStackTrace();  
              }  
          }  
          /** 
           * 建立索引 
           * @throws Exception 
           */  
          public static void addIndex(Article article) {  
              try {  
                  server.addBean(article);  
                  server.commit(true,true,true);  // 第三个true代表软提交  
              } catch (IOException e) {  
                  e.printStackTrace();  
              } catch (SolrServerException e) {  
                  e.printStackTrace();  
              }  
          }  
            
          /** 
           * 查询 
           */  
          @SuppressWarnings("unchecked")  
          public static Map<String,Object> search(String skey, Long start, Long row) throws Exception {  
              // schema.xmml中设置了id为uniquekey,增加索引时,如果id相同则更新索引,id不同则新增索引  
              SolrQuery param = new SolrQuery();  
              param.set("q","text:"+skey);  
              //param.set("fq","title:"title1"");   // fq与q的查询内容取交集,并把fq的内容缓存  
              param.addFacetField("title");  //按照title字段分组  
              param.setStart(start.intValue());  
              param.setRows(row.intValue());  
        
              param.setHighlight(true);  
              param.addHighlightField("title");  //给查询出title字段家高亮  
              param.addHighlightField("describe");  
              param.setHighlightSimplePre("<font color='red'>");  
              param.setHighlightSimplePost("</font>");  
        
              QueryResponse reponse = server.query(param);  
              List<Article> articleLi = reponse.getBeans(Article.class);  //  
              long numFound = reponse.getResults().getNumFound();  
        
              Map<String, Map<String, List<String>>> highlighting = reponse.getHighlighting(); // <id,{"title":"{list}","describe":{list}}>>  
              for (Article article : articleLi) {  
                  String id = article.getId();  
                  Map<String, List<String>> map = highlighting.get(id);  
        
                  List<String> titles = map.get("title");  
                  if(CollectionUtils.isNotEmpty(titles)){  
                      article.setTitle(titles.get(0));  
                  }  
        
                  List<String> describes = map.get("describe");  
                  if(CollectionUtils.isNotEmpty(describes)){  
                      article.setDescribe(describes.get(0));  
                  }  
              }  
        
              HashedMap hashedMap = new HashedMap();  
              hashedMap.put("dataList",articleLi);  
              hashedMap.put("nummFound",numFound);  
              System.out.println(hashedMap);  
              return hashedMap;  
          }  
            
          /** 拼写检查 */  
          public static void checkSpell(){  
              SolrQuery param = new SolrQuery();  
              param.set("q","title:title1");  
              param.set("qt","/spell");  
              try {  
                  QueryResponse response = server.query(param);  
                  SolrDocumentList results = response.getResults();  
                  long numFound = results.getNumFound();  
                  if(numFound==0){  
                      List<SpellCheckResponse.Suggestion> suggestions = response.getSpellCheckResponse().getSuggestions();  
                      for (SpellCheckResponse.Suggestion suggestion : suggestions) {  
                          int suggestNum = suggestion.getNumFound();  
                          System.out.printf("推荐词个数:"+suggestNum);  
                          List<String> list = suggestion.getAlternatives();  
                          for (String s : list) {  
                              System.out.println(s);  
                          }  
                      }  
                  }else{  
                      for (SolrDocument result : results) {  
                          Collection<String> fieldNames = result.getFieldNames();  
                          for (String fieldName : fieldNames) {  
                              Object value = result.get(fieldName);  
                              System.out.println("字段名:"+fieldName+",字段值:"+value);  
                          }  
                          System.out.println("===================================================");  
                      }  
                  }  
              } catch (SolrServerException e) {  
                  e.printStackTrace();  
              }  
          }  
        
          public static void main(String[] args) {  
              checkSpell();  
          }  
      }  
      

    十. solr时间问题

    solr的时间 , 页面上显示时间比真实事件少8小时, java代码操作的话没问题

    十一. solr的主从结构 (解决高并发响应速度慢的问题)

    1. master节点

      <lst name="master">            <!-- 主从结构时主节点应该打开此处配置-->
           <str name="replicateAfter">commit</str> <!--solrserver.commit()后从节点开始同步索引-->
           <str name="replicateAfter">startup</str> <!--从节点重启后开始同步索引-->
           <str name="confFiles">schema.xml,stopwords.txt</str>
      </lst>
      
    2. slave节点

      <lst name="slave">  <!--主从结构时,从节点修改的配置-->
           <str name="masterUrl">http://your-master-hostname:8983/solr/collection1</str><!--配置主节点url,-->
           <str name="pollInterval">00:00:60</str><!--每隔60--秒同步一次-->
      </lst>
      
    3. 动态切换主从角色 : 只需要把所有节点上面的配置都统一修改为下面配置即可

      <lst name="${master:master}">
           <str name="replicateAfter">commit</str>
           <str name="replicateAfter">startup</str>
           <str name="confFiles">schema.xml,stopwords.txt</str>
      </lst>
      <lst name="${slave:slave}">
           <str name="masterUrl">http://${masterurl}:8983/solr</str>
           <str name="pollInterval">00:00:60</str>
      </lst>
      
    4. 这样在启动的时候

      启动主节点:java -Dslave=disabled -Dmasterurl  -jar start.jar 
      启动从节点:java -Dmaster=disabled -Dmasterurl=192.168.1.170  -jar start.jar
      

    十二. solrcloud操作solr集群

    String zkHost = "192.168.1.170:2181,192.168.1.171:2181";
    CloudSolrServer server = new CloudSolrServer(zkHost );
    server.setDefaultCollection("collection1");
    SolrQuery query = new SolrQuery();
    query.set("q", "*:*");
    QueryResponse response = server.query(query);
    SolrDocumentList results = response.getResults();
    

    十三. solr的提交方式

    1. 代码手动提交 :
      (1)硬提交 : 把索引到硬盘中 (写index文件)

      httpSolrServer.commit();
      

    (2)软提交 :
    索引库中没有 , 但是能查询到 (软提交把数据提交到内存) , 但是会产生提交的log日志 , 在下次启动solr时,solr根据提交日志, 把数据恢复到index目录中 , 所以数据不会丢失. 这是一种兼顾实时性与性能的这种选择 (写log文件)
    java httpSolrServer.commit(true,true,true);
    2. 自动硬提交触发时,软提交的数据从内存刷到文件中
    (1)自动硬提交 :
    代码中不执行commit() , 每隔15秒提交一次索引到硬盘 , 或记录达到10000条自动提交 . 这种自动提交 , 如果false , 相当于没有重新刷新索引 , 所以自动提交后还是查不到. openSearch消耗性能,所以应该配置maxDoc与maxTime尽量大(solr中必须设置自动硬提交, 否则代码的软提交没法写成index索引文件 , 只是log文件+内存中的数据, 可能造成内存溢出 )

    ```xml
    <autoCommit> 
      <maxTime>${solr.autoCommit.maxTime:15000}</maxTime> 
     <!--  <maxDocs>10000</maxDocs>  -->
      <openSearcher>false</openSearcher> 
    </autoCommit>
    ```
    

    (2)自动软提交 (每隔多长时间吧内存中的数据写一次log日志)

    ```xml
    <autoSoftCommit> 
      <maxTime>${solr.autoSoftCommit.maxTime:1000}</maxTime> 
    </autoSoftCommit>
    ```
    
    
    
    【注】: 通常配置1-10分钟自动硬提交 , 每秒软提交
    关于存储字段和索引字段 : 例如sql: select id , auth from tableA where content='aa'  此时content作为索引字段进行查询(index=true),id.auth作为存储字段显示(stored=true)
    将多个索引文件合并成1个索引文件,避免发生too many files一场(linux系统抛出) httpSolrServer.optimize()代码 (消耗性能,应在夜晚执行)
    精确查询 : 不对查询字段的值进行分词 , params.set("q",content:"刘德华")
    

    十四. Solr与Hbase (hbase通过行健查询很快)

    1. 配置solrschema.xml : 修改field字段

      field name index store
      id index:true store:true
      title index:true store:true
      author index:false store:true
      describe index:true store:true
      content 该字段内容很多,index:false store:false
    2. 配置ik分词器
      (1)复制IkAnalyzer.jar到 solr-webapp/webapp/web-inf/lib
      (2)拷贝IKAnalyzer.cfg.xml和stopword.dic到solr-webapp/webapp/web-inf/目录下
      (3)修改schema.xml配置中文分词器

      <!--配置IK分词器-->  
      <fieldType name="text_ik" class="solr.TextField">  
          <!--索引时候的分词器-->  
          <analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>  
          <!--查询时候的分词器-->  
          <analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/>  
      </fieldType>  
      
      
  • 相关阅读:
    中国历史朝代公元对照简表
    [Solved] DashBoard – Excel Service: The data sources may be unreachable, may not be responding, or may have denied you access.
    Delete/Remove Project from TFS 2010
    Sharepoint site showing system account instead of my username on the top right corner.
    你的成功在于你每天养成的习惯
    Internet Information Services is running in 32bit emulation mode. Correct the issue listed above and rerun setup.
    Prepare to back up and restore a farm (Office SharePoint Server 2007)
    Word中字号与磅值的对应关系
    How to: Change the Frequency for Refreshing the Data Warehouse for Team System
    UI Automation in WPF/Silverlight
  • 原文地址:https://www.cnblogs.com/72808ljup/p/5564205.html
Copyright © 2011-2022 走看看