欢迎投稿

今日深度:

Solr入门,

Solr入门,


Solr入门

通过Solr实现全文搜索,如果每次通过访问数据库搜索全文,比如使用LIKE %,将会给服务器造成巨大的压力。

简介

Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。

Solr是一个全文检索服务器,只需要进行配置就可以实现全文检索服务。

安装及配置

首先版本Java 1.8/Tomcat8.5/solr 7.2.1

步骤:

1.       solr下载http://mirrors.hust.edu.cn/apache/lucene/solr/7.2.1/,解压为solr-7.2.1文件夹。

2.       将. \solr-7.2.1\server\solr-webapp文件夹复制到. \apache-tomcat-8.5.29\webapps下,并重命名为solr。

3.       将.\solr-7.2.1\server\lib\ext下的所有jar包,以及.\solr-7.2.1\server\lib下以metrics开头的jar、gmetric4j-1.0.7.jar复制到. \apache-tomcat-8.5.29\webapps\solr\WEB-INF\lib下。

4.       在. \apache-tomcat-8.5.29\webapps\solr\WEB-INF中,新建classes文件夹,将.\solr-7.2.1\server\resources下的log4j.properties文件拷贝到里面。

5.       创建一个D:\solr_home 的目录,并将.\solr-7.2.1\server\solr目录复制D:\solr_home目录下

6.       打开Tomcat/webapps/solr/WEB-INF下的web.xml,增加如下配置内容(初始状态下该内容是被注释掉的):

<env-entry>

      <env-entry-name>solr/home</env-entry-name>

      <env-entry-value>D:/solr_home</env-entry-value>

      <env-entry-type>java.lang.String</env-entry-type>

</env-entry>

将<env-entry-value>中的内容改成你的solr_home路径,这里是D:/solr_home。这项配置,要是建立tomcat与solr之间的关系的,的作用是让tomcat找到你所配置的solr目录。

以上操作配置完成后,启动Tomcat,如果出现报错,查看一下tomcat/logs下的日志文件,查看报错信息,我当时出现java.lang.NoClassDefFoundError:Failed to initialize Apache Solr: Could not find necessary SLF4j logging jars.这个错误,后来添加依赖slf4j-simple-1.7.25.jar后成功。

使用

添加新Core

1、在solr_home目录下创建新core的文件夹,如new_core,然后进入new_core再创建conf文件夹。

2、将.\solr-7.2.1\server\solr\configsets\_default\conf下的所有文件复制到刚刚创建的conf文件夹中,也就是将默认的配置文件复制过去。

3、打开solr,在core admin中点击Add Core,name和instanceDir都改为刚刚创建的新core的名字。

创建成功。

配置中文分词

1.       百度搜索下载ikanalyzer-solr6.5.zip,解压。

2.       将ik-analyzer-solr5-5.x.jar复制到.\ apache-tomcat-8.5.29\webapps\solr\WEB-INF\lib下。

3.       将KAnalyzer.cfg.xml、ext.dic(扩展词典)、stopword.dic(停用词典)复制到.\ apache-tomcat-8.5.29\ebapps\solr\WEB-INF\classes中。

4.       进入.\solr_home\(core_name)\conf下,就是core文件夹中修改managed-schema内容加上

<fieldType name="text_ik"class="solr.TextField">

 <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>

</fieldType>

保存后重启服务器,按照如下方法查看是否配置成功。

配置业务(搜索)字段

业务字段判断标准:

1、在搜索时是否需要在此字段上进行搜索。例如:新闻标题、新闻内容、新闻来源等。

2、后续的业务是否需要用到此字段。例如:新闻id。

进入.\solr_home\(core_name)\conf下,就是core文件夹中修改managed-schema,在刚刚添加的fieldType标签后面添加下面的内容

<fieldType name="text_ik"class="solr.TextField">

  <analyzerclass="org.wltea.analyzer.lucene.IKAnalyzer"/>

</fieldType>

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

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

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

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

<copyField source="news_title" dest="news_keywords"/>

<copyField source="content" dest="news_keywords"/>

<copyField source="ctype" dest="news_keywords"/>

注意indexed="true"表示开启索引(当字段不需要被检索时,最好不要开启索引) stored="true"表示存储原来数据(当字段不被检索,而只是需要通过其他字段检索而获得时,要设为true)  multiValued="true" 表示返回多值,如一个返回多个content,此时要在java代码中把 content设置 集合或数组类型如private String[] content;//多值,对应 multiValued="true"

重启服务器,可以看到刚刚配置的字段都在:


SolrJ基本使用

SolrJ是操作Solr的JAVA客户端,它提供了增加、修改、删除、查询Solr索引的JAVA接口。SolrJ针对 Solr提供了Rest 的HTTP接口进行了封装, SolrJ底层是通过使用httpClient中的方法来完成Solr的操作。

Maven依赖

<dependency>

 <groupId>org.apache.solr</groupId>

 <artifactId>solr-solrj</artifactId>

 <version>7.1.0</version>

</dependency>

 

SolrClient是一个抽象类,下边有很多被实现的子类,HttpSolrClient是通用客户端,可以与一个Solr节点直接通信。

SolrJ客户端创建

使用Tomcat启动本地地址,默认端口8080,URL指向我们配好的Core(newcore)。

String solrUrl = "http://127.0.0.1:8080/solr/newcore";
//创建solrClient同时指定超时时间,不指定走默认配置
HttpSolrClientclient = new HttpSolrClient.Builder(solrUrl)
        .withConnectionTimeout(
10000)
        .withSocketTimeout(
60000)
        .build()
;
//不同solr版本solrj 的创建方式有所不同
//solr4创建方式
//SolrServersolrServer = new HttpSolrServer("http://127.0.0.1:8080/solr");
//solr5
创建方式,url中指定core名称:newcore
//HttpSolrClient solrServer=newHttpSolrClient("http://127.0.0.1:8080/solr/newcore");
//solr7
创建方式,url中指定core名称:newcore
HttpSolrClient solrServer = new HttpSolrClient.Builder(
       
"http://127.0.0.1:8080/solr/newcore").build();

创建索引

创建文档,添加Field(k-v),使用SolrClient的add()方法,然后commit()。可以批量添加然后commit。

solr也是nosql的一种。更新索引则直接在原有基础上添加进行覆盖。

/**
 *
solrJ创建索引
 
* 添加索引使用SolrClientadd()方法
 
*/
@Test
public void solrAdd() throws Exception {
   
//创建文档doc
   
SolrInputDocument doc = new SolrInputDocument();
   
//添加内容
   
doc.addField("id", "13002");
   
doc.addField("news_title", "新闻标题2");
   
doc.addField("content", "新闻内容2");
   
doc.addField("ctype", "时政");
   
//添加到client
   
UpdateResponse updateResponse = client.add(doc);
   
System.out.println(updateResponse.getElapsedTime());
   
//索引文档必须commit
   
client.commit();
}

查询

/**
 *
查询
 
* SolrClient有很多quary() 查询方法用于从solr中获取结果,这些方法都需要一个SolrParams 类型的参数,
 
* 该对象可以封装任意的查询参数。和每个方法输出 QueryResponse 一个包装器,可以用来访问结果文档和其他相关的元数据。
 
*/
@Test
public void querySolr() throws Exception {
   
//封装查询参数
   
Map<String, String> queryParamMap = new HashMap<>();
   
queryParamMap.put("q", "*:*");
   
//添加到SolrParams对象
   
MapSolrParams queryParams = new MapSolrParams(queryParamMap);
   
//执行查询返回QueryResponse
   
QueryResponse response = client.query(queryParams);
   
//获取doc文档
   
SolrDocumentList documents =response.getResults();
    
//内容遍历
   
for (SolrDocument doc : documents) {
        System.
out.println("id:" + doc.get("id")
                +
"\tnews_title:" + doc.get("news_title")
                +
"\tcontent:" + doc.get("content")
                +
"\tctype:" + doc.get("ctype"));
   
}
   
client.close();
}

SolrParams 有一个 SolrQuery 子类,它提供了一些方法极大地简化了查询操作。

/**
 *
使用 SolrParams 的子类 SolrQuery,它提供了一些方便的方法,极大地简化了查询操作。
 
*/
@Test
public void querySolr2() throws Exception {
   
//封装查询参数
   
SolrQuery query = new SolrQuery("*:*");
   
//添加需要回显得内容
   
query.addField("id");
   
query.addField("news_title");
   
query.setRows(20);//设置每页显示多少条
   
//执行查询返回QueryResponse
   
QueryResponse response = client.query(query);
   
//获取doc文档
   
SolrDocumentList documents =response.getResults();
   
//内容遍历
   
for (SolrDocument doc : documents) {
        System.
out.println("id:" + doc.get("id")
                +
"\tnews_title:" + doc.get("news_title")
                +
"\tcontent:" + doc.get("content")
                +
"\tctype:" + doc.get("ctype"));//因为没添加回显内容查询为null
   
}
   
client.close();
}

删除索引

/**
 * 单个id的删除索引
 */
@Test
public void solrDelete() throws Exception {
    //通过id删除
    client.deleteById("13001");
    //提交
    client.commit();
    //关闭资源
    client.close();
}

/**
 * 多个idlist集合 删除索引
 */
@Test
public void solrDeleteList() throws Exception {
    ArrayList<String> ids = new ArrayList<>();
    ids.add("13001");
    ids.add("13002");
    client.deleteById(ids);
    //提交
    client.commit();
    //关闭资源
    client.close();
}

/**
 * 根据查询删除
 */
@Test
public void solrDeleteQuery() throws Exception {
    client.deleteByQuery("id:100");//删除满足查询条件的信息
    //提交
    client.commit();
    //关闭资源
    client.close();
}

SolrJ绑定Java对象

SolrJ支持通过@Field注解隐式转换文档与任何类。每个实例变量在Java对象可以映射到一个相应的Solr字段中。

定义一个Article的pojo。其中articleTitle和articleContent字段使用@Field注解,而author没有使用则不能映射到集合的索引中。

public class Article {
    @Field("articleTitle")
    private String articleTitle;
    @Field("articleContent")
    private String articleContent;
    private String author;

    public Article() {
        System.out.println("无参构造器");
    }
//gettersetter略
    ...
}

创建索引

/**
 * Java对象绑定,通过对象创建索引
 */
@Test
public void addBean() throws Exception{
    //创建对象
    Article article = new Article("北京的雪","北京的雪好美!","小明");
    Article article2 = new Article("南京的雪","南京不下雪!","小红");
    //添加对象
    UpdateResponse response = client.addBean(article);
    client.addBean(article2);
    //提交操作
    client.commit();
    //关闭资源
    client.close();
}

结果如下:

通过对象查询索引

这里会报一个错org.apache.solr.client.solrj.beans.BindingException:Could not instantiate object of class com.seu.fn.bean.Article。首先,映射的pojo的类需要有无参构造函数(在该构造器中设置输出,会看到调用的结果)。然后在managed-schema文件中,配置对应字段的类型。由于之前插入,会自动生成text_general的类型,需要修改成text_ik类型,即我们之前配置的支持中文分词的类型,同时还可以设置indexed="true"stored="true"。然后再运行,输出正常。

/**
 * Java对象绑定,通过对象查询索引
 */
@Test
public void queryBean() throws Exception{
    //创建SolrQuery对象
    SolrQuery query = new SolrQuery("*:*");
    //添加回显的内容
    query.addField("articleTitle");
    query.addField("articleContent");

    query.setRows(200);//设置每页显示多少条
    //执行查询返回QueryResponse
    QueryResponse response = client.query(query);
    //获取doc文档
    List<Article> articles = response.getBeans(Article.class);
    //遍历
    for (Article article : articles) {
        System.out.println("title:"+article.getArticleTitle()
                +"\tauthor:"+article.getAuthor()
                +"\tcontent:"+article.getArticleContent());
    }
    //关闭资源
    client.close();
}

 

整合Spring

编写applicationContext-solr.xml

添加:

<bean id="httpSolrClient"class="org.apache.solr.client.solrj.impl.HttpSolrClient">
    <constructor-arg
name="builder" value="${SOLR.SERVER.URL}"></constructor-arg>
</bean>

solr.properties文件中添加:

SOLR.SERVER.URL=http://127.0.0.1:8080/solr/corename

然后就可以使用@Autowired进行使用HttpSolrClient对象了。

 

从数据库导入数据Dataimport

上面提到的都是一些基本用法,但是面对从数据库中导入大量的数据时,如果还傻傻的一个一个addField和commit(我尝试过),效率就太慢了。。。

随即百度一波,学习记录下。

步骤:

1、修改.\solr_home\copyrightCore\conf\solrconfig.xml文件,添加

<requestHandler name="/dataimport"class="org.apache.solr.handler.dataimport.DataImportHandler">

  <lstname="defaults">

    <strname="config">db-data-config.xml</str>

  </lst>

</requestHandler>

2、在conf目录下创建上面标红的文件db-data-config.xml,并添加:

<?xml version="1.0"encoding="UTF-8" ?>

<dataConfig>

<dataSourcedriver="com.mysql.jdbc.Driver"url="jdbc:mysql://localhost:3306/copyright_test"user="root" password="root" />

<document>

<entity name="news_info" query="selectnews_id,title,author,editor,source,ctype,keywords from news_info">

            <fieldcolumn="news_id" name="newsId"/>

            <fieldcolumn="title" name="title"/>

            <fieldcolumn="author" name="author"/>

            <fieldcolumn="editor" name="editor"/>

            <fieldcolumn="source" name="source"/>

            <field column="ctype"name="ctype"/>

            <fieldcolumn="keywords" name="keywords"/>

</entity>

</document>

</dataConfig>

其中entity name=“对应的数据库表名”,后面的query就是sql语句,field column一定要对应数据库的列名,不然导入不进去,后面的name为managed-shchema中配置的字段名,即在solr中显示的字段。

3、两个jar包是必须的,当然其他jar包在上面配置中已经配置过。

mysql-connector-java-5.1.7-bin.jar(MySQL的jar包肯定是必须的)

solr-dataimporthandler-7.2.1.jar(看名字大概知道是dataimport相关的,在.\solr-7.2.1\dist目录下)

4、配置managed-shchema文件中的字段名,名字要和数据库一一对应,当然不想显示的字段可以不配置。配置如下(部分略):

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

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

。。。等。注意,如果出现报错说xml格式的问题,最好复制文件中默认配置的格式然后进行修改。

5、启动solr,进入控制界面。

进入Dataimport页面,然后选择Auto-Refresh Status,点击Execute。

导入成功。

www.htsjk.Com true http://www.htsjk.com/solr/38320.html NewsArticle Solr入门, Solr入门 通过Solr实现全文搜索,如果每次通过访问数据库搜索全文,比如使用LIKE %,将会给服务器造成巨大的压力。 简介 Solr 是Apache下的一个顶级开源项目,采用Java开发,它...
相关文章
    暂无相关文章
评论暂时关闭