solr

solr

1. 简介

solr是基于Apache Lucene构建的搜索服务器,Apache Lunce是基于Java的开源信息检索库。
在这里插入图片描述

2. 安装

solr基于lucene,lucene为Java所写,自然要jdk,新版本solr要jdk-1.8及以上。
下载src.tgz包,解压,进入bin目录

# 启动
./solr start
# 停止
./solr stop

注意:solr拒接以root身份启动,需要加-force才可以,推荐使用普通用户。默认端口为8983

#指定端口
bin/solr start -p 8655
bin/solr restart [options]
bin/solr restart -help
bin/solr stop -help
#停止所有正在运行的具有有效PID的Solr实例。
bin/solr stop -all
#kill -s 9 [pid]
3. solr核心

solr中一个核心(core)相当于一个搜索引擎,然后上传文件时也是上传到指定核心;solr可以建立多个solr。solr默认没有core,我们先来创建一个core。
通过命令创建和删除core:

# 创建core,-c指定创建的core名
./solr create -c new_core
# 删除core,-c指定删除的core名
./solr delete -c new_core

注意:也可以在页面新建,但是有bug

Error CREATEing SolrCore ‘new_core’: Unable to create core [new_core] Caused by: Can’t find resource ‘solrconfig.xml’ in classpath

cp -r /root/solr-8.1.1/server/solr/configsets/_default/conf /root/solr-8.1.1/server/solr/new_core

首先去目录:solr安装目录/solr-8.1.1\server\solr/ 创建一个名字为new_core的文件夹然后拷贝当前目录下:solr安装目录/solr-8.1.1\server\solr\configsets_default下的conf目录拷贝到new_core目录下

4. 上传文件创建索引
./post -c test_core1 ../example/example
5. 相关索引库配置

schema.xml 是用来定义索引数据中的域的,包括域名称,域类型,域是否索引,是否分词,是否存储等等。

如何定义索引库中的 Field
<field>:定义域 <field name="_version_" type="long" indexed="true" stored="true"/>
name:表示域的名称,是强制必须有的属性 
type:域类型的名称,与fieldType元素的name属性值对应,是强制必须有的属性 
indexed:是否参与检索。true即表示需要对该域进行索引。默认值为false 
stored:是否将field域中的内容存储到文档域,简单通俗的来说,就是你这一个field需不需要被当作查询结果返回。 required:表示这个域是否是必须要在document中存在,默认值为false,如果此配置项设为true,则你的document中必须要添加此域,否则你创建索引时会抛异常。 
如何定义索引库中的 FieldType
<fieldType>:定义域的类型 
<fieldType name="string" class="solr.StrField" sortMissingLast="true" /> 
Name:域类型的名称,作为域类型标识符存在,在定义域(Field)时使用的类型(FieldType)属性就是域类型的名称。 
Class:域类型的数据类型,该属性指向的是solr中的已定义的类型,或者是用户定义的类型,域类型中的数据会被初始化成class执行类类的对象。 
sortMissingFirst/sortMissingLast:控制当排序域的值不存在时该文档(Document)所在队列的位置。true是则在队头/队尾 
如何定义索引库中的 CopyField
<copyField>:复制域。可实现更新与查询分离
<copyField source="item_title" dest="item_keywords"/>
Source:源域 
Dest:目标域
dataimport 导入数据库数据

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

jar包导入server/solr-webapp/webapp/WEB-INF/lib下

数据库连接jar包 以及dataimport2个jar包

新建data-config.xml

<dataConfig>  
  <dataSource name="source1"  type="JdbcDataSource"   
              driver="com.mysql.jdbc.Driver"  
              url="jdbc:mysql://xxx.xxx.xxx.xx:3306/JTest"   
              user="root"   
              password="root"/>  
  <document >  
    <entity name="Test" dataSource="source1"  PK="id"  
            query="SELECT id,name,adress from Test">
            <!--每一个field映射着数据库中列与文档中的域,column是数据库列,name是solr的域(必须是在managed-schema文件中配置过的域才行) -->
            <field column="id"  name="id" />
            <field column="name"  name="name" />
            <field column="adress"  name="adress" />
    </entity> 
  </document>  
</dataConfig> 

managed-schema 添加

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

solrconfig.xml 添加

<requestHandler name="/dataimport" class="solr.DataImportHandler"> 
      <lst name="defaults"> 
        <str name="config">data-config.xml</str> 
      </lst> 
</requestHandler>
代码solrj的使用
<dependency>
    <groupId>org.apache.solr</groupId>
    <artifactId>solr-solrj</artifactId>
    <version>5.5.2</version>
</dependency>

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

代码很好理解,直接给出

private String serverUrl = "http://xxx.xxx.x.x:8080/solr/core1";
    /**
     * 增加与修改<br>
     * 增加与修改其实是一回事,只要id不存在,则增加,如果id存在,则是修改
     * @throws IOException 
     * @throws SolrServerException 
     */
    @Test
    public void upadteIndex() throws SolrServerException, IOException{
        //已废弃的方法
        //HttpSolrServer server = new HttpSolrServer("http://xxx.xxx.x.x: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();
    }

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

/**
 * 删除索引
 * @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();
    }

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

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

参数描述
q这是Apache Solr的主要查询参数,只输入值有时不能搜索,使用键值形式最稳妥,查询字符串,如果查询所有*😗 (id:1)
fq这个参数表示Apache Solr的过滤器查询,将结果集限制为与此过滤器匹配的文档.(filter query)过虑查询,过滤条件,基于查询出来的结果
fl指定返回那些字段内容,用逗号或空格分隔多个。
start分页开始,此参数的默认值为0
rows分页查询数据,此参数的默认值为10
sort这个参数指定由逗号分隔的字段列表,根据该列表对查询的结果进行排序,格式:sort=+ [,+ ]……。示例:(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
  • “:” 指定字段查指定值,如返回所有值* : *
  • “?” 表示单个任意字符的通配
  • “*” 表示多个任意字符的通配(不能在检索的项开始使用 *或者?符号)
  • “~” 表示模糊检索,如检索拼写类似于”roam”的项这样写:roam~ 将找到形如foam和roams的单词;roam~0.8,检索返回相似度在0.8以上的记录。
  • 邻近检索,如检索相隔10个单词的”apache”和”jakarta”,”jakarta apache”~10
  • “^” 控制相关度检索,如检索jakarta apache,同时希望去让”jakarta”的相关度更加好,那么在其后加上 ”^” 符号和增量值,即jakarta^4 apache
  • 布尔操作符AND、||
  • 布尔操作符OR、&&
  • 布尔操作符NOT、!、- (排除操作符不能单独与项使用构成查询)
  • “+” 存在操作符,要求符号”+”后的项必须在文档相应的域中存在
  • ( ) 用于构成子查询
  • [] 包含范围检索,如检索某时间段记录,包含头尾,date:[200707 TO 200710]
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;

/**
 * 搜索
 *
 */
public class IndexSearch {

    private String serverUrl = "http://xxx.xxx.x.x: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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值