爬虫(三):Solr

  • lucene的索引的修改和删除
  • solr:
      1. solr的概念
      1. solr的部署(2种方式)
      1. solr的管理界面
      1. solr的配置文件: solrConfig.xml schema.xml core.properties
      1. solrj 连接solr 相关的操作: C U R D
      1. solr的高级: 高亮 分页 排序

1. lucene的索引的修改和删除

  • 索引的修改
public class LuceneEdit {
    //lucene的修改, 本质上先删除原有的数据, 然后进行添加索引
    public static void main(String[] args) throws IOException {
        //1. 创建索引写入器对象
        Directory directory = FSDirectory.open(new File("f:\\index"));
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST,new IKAnalyzer());
        IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);

        //2. 修改索引
        Document doc = new Document(); //此处的document是修改后的数据
        doc.add(new LongField("id",21L, Field.Store.YES));
        doc.add(new StringField("title","今天讲solr了,这是修改后的内容", Field.Store.YES));
        indexWriter.updateDocument(new Term("title","lucene的简介"),doc);

        //3. 提交索引
        indexWriter.commit();

        //4. 关闭
        indexWriter.close();
    }
}

  • lucene的索引的删除
public class LuceneDelete {
    //索引的删除
    public static void main(String[] args) throws IOException {
        //1. 创建indexWriter对象
        Directory directory = FSDirectory.open(new File("f:\\index"));
        IndexWriterConfig indexWriterConfig  = new IndexWriterConfig(Version.LATEST,new IKAnalyzer());
        IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);

        //2. 索引的删除
        indexWriter.deleteAll();//删除全部
        //indexWriter.deleteDocuments(query);//根据条件删除
        //indexWriter.deleteDocuments(new Term("title","今天讲solr了,这是修改后的内容"));//根据词条删除

        //3. 提交
        indexWriter.commit();

        //4. 关闭
        indexWriter.close();
    }
}

2. solr

solr是一个独立的企业级的搜索应用服务器, 如果想从服务器中获取数据, 那么就需要使用http请求发送, solr的是基于lucene实现的, 底层就是lucene

3.solr的部署

3.1 solr的下载:

3.2 solr的目录结构

3.3 solr服务的部署

3.3.1 使用start.jar部署solr服务
  • 部署步骤:
      1. 打开cmd, 切换start.jar这个目录下
      1. 执行 java -jar start.jar
      1. 访问管理界面: localhost:8983/solr
3.3.2 使用solr.war进行部署(重点)

准备工作:

​ 在一个没有中文和空格的地方, 创建一个目录, 目录名(solr), 把tomcat放置到solr目录中

​ 在使用tomcat之前, 先进行tomcat的测试(启动一个tomcat)

如果tomcat已启动就闪退:

​ 检查jdk的环境变量:

​ jdk的环境错误: JAVA_HOME 此单词写错了

  • 步骤1: 先将solr.war放置到一个空的tomcat中的webapps目录下

  • 第二步: 启动tomcat, 解压solr.war

    • 注意: 启动解压完毕以后, 请必须将tomcat关闭
  • 第三步: 将原来solr.war删除, 或者更改其后缀名称

  • 第四步: 打开解压后的solr目录, 从资料中将tomcat运行的jar包和配置文件复制到solr里面去

  • 第五步: 复制example里面的solr目录里面的所有的内容, 将其复制到 和tomcat同级的目录(solr-home)中

  • 第六步: 打开tomcat中bin目录下的Catalina.bat

  • 第七步: 设置如下的参数:保存关闭

    • 内容
set "JAVA_OPTS=-Dsolr.solr.home=D:\JAVA_Soft\solr\solr-home"
  • 第八步:启动tomcat, 测试, 是否成功

4. solr的管理界面

  • 仪表盘

  • logging: 日志显示

解决一下警告(可选):

  • 第一步:

  • 第二步: 修改配置文件

  • core admin

如何配置多个索引库:(推荐一种比较简单的方案)

  • 第一步: 将collection1复制出来一个, 进行更改名称(名称可以自定义)

  • 第二步: 打开新复制的出来的索引库, 找到core.properties,打开此文件

  • 第三步: 修改此配置文件中的name名称(自定义, 可以不和文件名称一致)

  • 重新启动tomcat即可

建议: 在设置一个新的索引库的时候, 建议将新复制出来的索引库中data的目录删除掉

  • core selector

  • documents

  • query

  • schema browser

5. solr的配置文件

5.1 solrConfig.xml:

solrconfig.xml 配置文件主要定义了 solr 的一些处理规则,包括索引数据的存放 位置,更新,删除,查询的一些规则配置。

​ 一般此文件不需要进行修改, 采取默认即可

在实际的使用中: 一般这个文件可以做相关solr的优化的

5.2 schema.xml:约束文件

在schema文件中, 指定了solr的字段, 字段类型, 使用什么分词器, 主键相关设置

<schema name="example" version="1.5">
   <!-- 不删除
   --> 
   <field name="_version_" type="long" indexed="true" stored="true"/>
   <field name="_root_" type="string" indexed="true" stored="false"/>
   <!-- 不删除
	field: 字段, 指定文档的字段的
		name: 字段的名称
		type: 字段的类型
		indexed: 是否索引
		stored: 是否存储
		required: 是否必须
		multiValued: 是否多值(此字段是一个数组)
	id这个字段: 是solr的文档的主键字段, 必须进行设置, 这是文档的唯一标识
		id在solr中是需要程序员自己维护, lucene文档的id是有lucene自己维护的
   -->   
   <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
  
   <field name="name" type="string" indexed="true" stored="true"/>
   
   <field name="title" type="string" indexed="true" stored="true" multiValued="true"/>
   
   <field name="content" type="string" indexed="false" stored="true" multiValued="true"/>
   
   <field name="text" type="string" indexed="true" stored="false" multiValued="true"/>
  
   <!-- 
	dynamicField: 动态域, solr中无法将所有的字段全部都定义好,此时solr为了能够进行扩展, 采用动态域
		当进行添加文档的时候, 只需要保证其后缀的名称和动态域的名称一致即可, 这样就可以添加任意的字段了	
   -->
   <dynamicField name="*_t"  type="string"    indexed="true"  stored="true"/>
 <!-- 
	uniqueKey :唯一主键 , 此处是用于定义主键字段的
		solr支持给任意字段设置为主键, 但是一般不这么干, 通常都是使用id
   -->
 <uniqueKey>id</uniqueKey>
	<!--
		copyField: 复制域, 主要是用来做搜索的, 可以将其他多个字段的数据合并到一个字段里面去, 这样当查询复制域的字段的时候 
			就相关于查询了多个字段
			source: 来源字段, 复制那个字段
			dest: 目的字段, 将数据复制到那个字段里面去
			
	-->
   <copyField source="title" dest="text"/>
   <copyField source="content" dest="text"/>
   <!--
		fieldType: 字段的类型, 指定某个字段的类型的, 可以指定字段类型使用分词器
   -->
    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />

    <!-- boolean type: "true" or "false" -->
    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
    <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
</schema>

5.3 引入ik分词器

  • 第一步: 导入ik分词器的jar包
    • 这一步骤在部署solr的时候, 已经就将其复制到了solr的lib目录里面去了
  • 第二步: 导入ik分词器的配置文件
    • 这一步其实已经做了, 在部署tomcat的时候导入一个classes,
  • 第三步: 修改schema.xml配置文件, 添加ik分词器的字段类型
<fieldType name="text_ik" class="solr.TextField">
		<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
 </fieldType>
  • 第四步: 给指定的字段设置此字段类型

注意: 在进行配置文件修改的时候, 请按照以下的修改

  • 第五步: 测试ik是否正常使用

6 solrj

solrj: 是apache开发的一个java连接solr的服务器的工具包, 使用solrj就可以对solr服务中数据进行CURDL

6.1 基本入门

  • 第一步: 导包
	<dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solr-solrj</artifactId>
            <version>4.10.2</version>
        </dependency>
        <!--日志的包, solrj执行需要一个日志包-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging-api</artifactId>
            <version>1.1</version>
        </dependency>
  • 第二步: 编写代码(写入索引库的操作)
public class IndexWriterToSolr {
    @Test
    public  void indexWriterToOne() throws IOException, SolrServerException {
        //1. 创建solrj连接solr的服务端对象
        /*
        * http://localhost:8080/solr/itcast: solr的接口的url
        *
        * http://localhost:8080/solr/#/itcast: 是浏览器的url
        * */
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/itcast");

        List<SolrInputDocument> list = new ArrayList<SolrInputDocument>();
        for(int i = 1 ; i<=10 ; i++){
            //2. 添加document对象
            SolrInputDocument doc = new SolrInputDocument();
            //2.1 向文档中添加数据
            //注意: 字段的名称必须是schema中定义好的, 要不然就使用动态域
            doc.addField("id",i);
            doc.addField("name","*");
            doc.addField("content","**");
            doc.addField("age",58+i);

            list.add(doc);
        }
        //solrServer.add(doc);
        solrServer.add(list);
        //3. 提交文档
        solrServer.commit();//提交的时候, 就当于发送了一个请求
    }
}

  • 使用javaBean添加索引
 @Test
    public  void indexWriterToTwo() throws IOException, SolrServerException {
        //1. 创建solrServer服务对象
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/itcast");

        List<User> list = new ArrayList<User>();

        //2. 添加文档
        for(int i = 12 ;i<=17; i++){
            User user = new User();
            user.setId(i+"");
            user.setName("*");
            user.setAge(78+i+"");
            user.setTitle(new String[]{"**"});
            user.setContent("***");

            list.add(user);
        }


        //solrServer.addBean(user);
        solrServer.addBeans(list);
        //3. 提交数据
        solrServer.commit();

    }

6.2 删除索引

public class DeleteIndexToSolr {

    @Test
    public  void deleteIndex() throws IOException, SolrServerException {
        //1. 创建solrServer服务对象
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/itcast");

        //2. 执行删除:  字段名称:字段的值
        //solrServer.deleteByQuery("age:59");
        solrServer.deleteById("2");
        //3. 提交
        solrServer.commit();
    }
}

6.3 索引的查询

6.3.1 基本查询的入门程序
@Test
    public void  queryToSolrofOne() throws SolrServerException {
        //1. 创建solrj连接solr的服务对象
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/itcast");

        //2. 执行查询
        SolrQuery solrQuery = new SolrQuery("*:*");
        solrQuery.setRows(100);
        QueryResponse response = solrServer.query(solrQuery);

        //3. 获取数据: document对象

        SolrDocumentList documentList = response.getResults();

        //4. 遍历集合 ,获取数据
        for (SolrDocument document : documentList) {
            Object id = document.get("id");

            Object age = document.get("age");
            Object content = document.get("content");
            System.out.println(id+"  "+age+ "  "+ content);
        }
    }
  • 返回javaBean的形式
public class User {
    // @Field: 指定当前这个成员属性是一个solr的字段
    @Field
    private String  id;
    @Field
    private String  name;
    @Field
    private Integer  age;
    @Field
    private String  content;
    @Field
    private String[]  title;
//缺失 get 和set 
}
  • 编写代码
//返回javaBean
    @Test
    public void  queryToSolrofTwo() throws SolrServerException {
        //1. 创建solrServer服务对象
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/itcast");

        //2. 执行查询
        QueryResponse response = solrServer.query(new SolrQuery("*:*"));

        //3. 解析结果:
        // 注意: 当返回的是javaBean的时候, 一定要注意, javaBean必须有无参构造
        List<User> userList = response.getBeans(User.class);

        for (User user : userList) {
            System.out.println(user);
        }
    }

6.3.2 多样化的查询

在创建SolrQuery时,我们填写的Query语句,可以有以下高级写法:

查询语句中如果有特殊字符,需要转义,可以使用: ” ”

1、匹配所有文档:*? (通配符?和 * :“*”表示匹配任意字符;“?”表示匹配出现的位置)

2、布尔操作:AND、OR和NOT布尔操作(推荐使用大写,区分普通字段)

3、子表达式查询(子查询):可以使用“()”构造子查询。 比如:(query1 AND query2) OR (query3 AND query4)

4、相似度查询:

(1)默认相似度查询:title:appla~,此时默认编辑距离是2

(2)指定编辑距离的相似度查询:对模糊查询可以设置编辑距离,可选02的整数:title:appla1。

5、范围查询(Range Query):Lucene支持对数字、日期甚至文本的范围查询,并且两端范围。结束的范围可以使用“*”通配符。

(1)日期范围(ISO-8601 时间GMT):birthday:[1990-01-01T00:00:00.000Z TO 1999-12-31T24:59:99.999Z]

(2)数字:age:[2000 TO *]

(3)文本:content:[a TO a]

  • 通配符的查询
 //统配符查询
    // ? : 占用一个符号
    // * : 占用 0 到 多个
    @Test
    public void  queryToSolrofThree() throws SolrServerException {
        //1. 创建 solrServer服务对象
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/itcast");

        //2. 执行查询
        SolrQuery solrQuery = new SolrQuery("title:简*");
        QueryResponse response = solrServer.query(solrQuery);
        //3. 解析结果:
        // 注意: 当返回的是javaBean的时候, 一定要注意, javaBean必须有无参构造
        List<User> userList = response.getBeans(User.class);

        for (User user : userList) {
            System.out.println(user);
        }
    }
  • 布尔查询
    //布尔查询
    // AND  OR NOT
    //当使用java代码进行查询的时候, 发现没有获取到数据,是不是代码写的有问题
    //  直接将条件内容, 放置到solr的管理界面进行测试执行
    @Test
    public void  queryToSolrof4() throws SolrServerException {
        SolrQuery solrQuery = new SolrQuery("title:简介 NOT age:95 NOT age:90");
        baseQuery(solrQuery);
    }
  • 子查询
    //子查询
    @Test
    public void  queryToSolrof5() throws SolrServerException {
       
        SolrQuery solrQuery = new SolrQuery("(title:简介 NOT age:95) AND (content:javaweb OR name:*)");

        baseQuery(solrQuery);
    }
  • 相似度查询
    //相似度查询: lucene的模糊查询
    //  最大编辑次数: 2次
    // 在solr中使用 ~
    //  solr中 ~后面添加了大于2 , 使用默认为2
    // 如果~ 后面添加小于0的, 使用默认为2
    @Test
    public void  queryToSolrof6() throws SolrServerException {
        // javaweb~
        SolrQuery solrQuery = new SolrQuery("content:javaw~");
        baseQuery(solrQuery);
    }
  • 范围查询
    //范围查询
	// 格式: [起始值 TO 结束值]  包含边界值
    @Test
    public void  queryToSolrof7() throws SolrServerException {
        //字典顺序
        SolrQuery solrQuery = new SolrQuery("id:[2 TO 9]");
        baseQuery(solrQuery);
    }

7. solr高级

7.1 solr的排序

    //solr的排序
    @Test
    public void solrSort() throws SolrServerException {
        SolrQuery solrQuery = new SolrQuery("*:*");

        //solrQuery.setSort(new SolrQuery.SortClause("age", SolrQuery.ORDER.desc));
        solrQuery.setSort("age", SolrQuery.ORDER.desc);
        baseQuery(solrQuery);
    }

7.2 solr的分页

    @Test
    public void limitToSolr() throws SolrServerException {
        //分页的参数
        int page = 3;
        int rows = 3;

        SolrQuery solrQuery = new SolrQuery("*:*");
        solrQuery.setStart((page-1)*rows); //设置起始值
        solrQuery.setRows(rows); //每页显示的条数

        baseQuery(solrQuery);
    }

7.3 solr的高亮

    @Test
    public void highlighterToSolr() throws SolrServerException {
        //1. 创建solrServer
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/itcast");

        //2. 执行查询
        SolrQuery solrQuery = new SolrQuery("content:javaweb");
        solrQuery.setHighlight(true);//开启高亮
        solrQuery.addHighlightField("content");//设置高亮的字段
        solrQuery.setHighlightSimplePre("<font color='red'>");
        solrQuery.setHighlightSimplePost("</font>");
        QueryResponse response = solrServer.query(solrQuery);

        /**
         * 最外层的map:
         *      key:  文档的id值
         *      value: 当前文档的高亮内容
         * 内层的map:
         *      key: 高亮的字段
         *      value: 高亮的内容(list一般只有一个)
         *
         */
        Map<String, Map<String, List<String>>> map = response.getHighlighting();
        //单独获取高亮的内容
        for (String key : map.keySet()) {
            Map<String, List<String>> stringListMap = map.get(key);
            for (String fieldKey : stringListMap.keySet()) {
                List<String> list = stringListMap.get(fieldKey);
                System.out.println(list.get(0));
            }
        }

        //3. 获取javaBean
        List<User> userList = response.getBeans(User.class);
        for (User user : userList) {
            //与结果集进行结合
            Map<String, List<String>> map1 = map.get(user.getId());


            user.setContent(map1.get("content").get(0));

            System.out.println(user);
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值