Solr操作

本文详细介绍了Solr的核心配置文件solrConfig.xml和schema.xml,包括字段定义、索引规则和存储规则。同时,文章讲解了如何引入Ik分词器,并展示了使用SolrJ进行索引的创建、读取、删除和更新,以及Solr的高级特性,如排序、分页和高亮显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

solrConfig.xml : solr的核心配置文件
​ solrconfig.xml 配置文件主要定义了 solr 的一些处理规则,包括索引数据的存放 位置,更新,删除,查询的一些规则配置。
​ 一般此文件不需要进行修改, 采取默认即可
schema.xml: solr约束文件
​ Solr中会提前对文档中的字段进行定义,并且在schema.xml中对这些字段的属性进行约束,例如:字段数据类型、字段是否索引、是否存储、是否分词等等


<!–name: 字段的名称
type: 字段的类型
indexed: 是否索引
stored: 是否保存
multiValued: 是否多值, 这个字段, 类似存储一个数组
这里有两个不允许删除的: 一个是 version_ 一个是 root_ 这两个是solr内部需要使用的字段

    有一个字段的名称必须为id,其类型都不允许进行修改 原因是id字段已经被主键使用uniqueKey  
    其余的是一些初始化好的字段
--> 
<!--第二种标签为dynamicField, 被称为是动态字段 --> 
<dynamicField name="*_is" type="int"    indexed="true"  stored="true"  multiValued="true"/>
    <!--此种标签是为程序的扩展所使用的, 因为我们不可能把所有的字段全部定义好, 所以就需要动态域来进行动态扩展--> 


<!--第三种标签为 uniqueKey:  必要标签, 表名文档的唯一属性, 一般默认为id-->  
    <uniqueKey>id</uniqueKey>
    <!--Lucene中是自己进行维护, solr中, 需要自己指定-->    

<!--第四种标签为 copyField: 被称为是复制域-->    
<copyField source="cat" dest="text"/>
    <!--source: 表名要复制那个字段的值
    dest: 复制到那个字段上
    
    此种标签主要是为了查询所使用的,
    例如, 当查询Text字段的时候, 实质上相当于查询title和name两个字段--> 

<!--第五种标签: fieldType   字段类型定义标签-->  
    <fieldType name="managed_en" class="solr.TextField" positionIncrementGap="100">
      <analyzer>
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.ManagedStopFilterFactory" managed="english" />
        <filter class="solr.ManagedSynonymFilterFactory" managed="english" />
      </analyzer>
    </fieldType>

引入ik分词器
•第一步: 导入ik相关的依赖包
•将三个文件放置在tomcat>webapps>solr>WEB-INF>lib下(此步骤在部署solr到tomcat中的时候, 就已经导入了)

•第二步: 导入ik相关的配置文件(ik配置文件, 扩展词典和停止词典)
•将三个文件放置在tomcat>webapps>solr>WEB-INF>classes下(此步骤, 在部署solr到tomcat中的时候, 已经导入)

•第三步, 在schema.xml配置文件中自定义一个字段类型, 引入ik分词器


•第四步: 为对应的字段设置为text_ik类型即可

solr的客户端操作: solrj
​ solrj是Apache官方提供的一套java开发的, 用于操作solr服务的API, 通过这套API可以让程序与solr服务进行交互, 让java程序可以直接操作solr服务进行增删改查
solrj的官网网址: https://wiki.apache.org/solr/Solrj
solr的基本入门程序
•第一步: 导入相关的jar包

org.apache.solr
solr-solrj
4.10.2



commons-logging
commons-logging-api
1.1

•编写入门程序(写入索引)
//使用solr 进行索引的写入 (原生的写入方式)
public class IndexWriterSolr {

public static void main(String[] args) throws Exception {
    //1. 创建solr的服务对象(发送请求, 获取数据)
    SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/collection1");

    //2. 添加索引
    /*SolrInputDocument doc = new SolrInputDocument();
    doc.addField("id","1");
    doc.addField("title","双十一来了");
    doc.addField("content","又到了卖肾的季节了");

    solrServer.add(doc);*/
    List<SolrInputDocument>  docs = new ArrayList<SolrInputDocument>();

    SolrInputDocument doc = new SolrInputDocument();
    doc.addField("id","1");
    doc.addField("title","双十一来了");
    doc.addField("content","又到了卖肾的季节了");
    docs.add(doc);
    SolrInputDocument doc1 = new SolrInputDocument();
    doc1.addField("id","2");
    doc1.addField("title","剁手节来了");
    doc1.addField("content","今天你剁手了吗?");
    docs.add(doc1);

    solrServer.add(docs);
    //3. 提交数据
    solrServer.commit();



}

}
solrj写入索引2(写入多条索引)
//2. 写入多条索引
@Test
public void createManyIndexToSolr() throws IOException, SolrServerException {
//1. 创建solrServer对象
SolrServer solrServer = new HttpSolrServer(“http://localhost:8080/solr/collection1”);
//2.1 设置多条数据
List docs = new ArrayList<>();
for(int i=0 ; i<10 ; i++){
//2.1.1 创建一个document
SolrInputDocument document = new SolrInputDocument();
document.addField(“id”,i);
document.addField(“content”,"solr是一个独立的企业级搜索应用服务器, 可以通过http请求访问这个服务器, 获取或者写入对应的内容, 其底层是Lucene "+i);
document.addField(“title”,“solr的简介”);

        //2.1.2 将document添加到集合中
        docs.add(document);
    }

    //2. 写入索引
    solrServer.add(docs);

    //3. 提交索引
    solrServer.commit();
}

使用solrj写入索引3(使用javabean进行写入)
•javaBean:
•注意事项:
–如果使用javaBean进行数据添加时, 需要给对应要加入索引库的字段添加@Field,用来指定其实一个document字段
–javaBean中的字段必须提前在solr的schema.xml中提前定义好
public class News {
@Field
private String id;
@Field
private String title;
@Field
private String content;
@Field
private String url;
//此处省略了 get 和 set方法
}
•操作代码
//使用javaBean来添加索引数据

@Test
public  void indexWriterToJavaBean() throws Exception {
    //1. 创建  solr的服务对象
    SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/collection1");

    //2. 添加文档数据
    News news = new News("3","Ella老公被曝呛声片场工作人员:我有的是钱","就怕因此拍摄不顺或当机,赖斯翔虽听从规劝,却也反呛","http://ent.163.com/18/1107/10/E00KM09000038FO9.html");

    solrServer.addBean(news);
    // 使用addBeans来添加多条数据

    //3. 提交数据
    solrServer.commit();
}

删除索引
//索引的修改和删除: 修改: 只要保证id一致, 就是在修改数据

@Test
public void delIndex() throws Exception {
    //1. 创建 solr的服务对象
    SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/collection1");

    //2. 执行删除
    //solrServer.deleteByQuery("*:*"); //删除全部的数据

    solrServer.deleteById("change.me");

    //3. 提交数据
    solrServer.commit();

}

查询操作
@Test
public void indexSearcherSolrTest01() throws Exception {
//1. 创建 solrServer对象
SolrServer solrServer = new HttpSolrServer(“http://localhost:8080/solr/collection1”);

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

    //3. 获取数据
    SolrDocumentList documentList = response.getResults();
    for (SolrDocument document : documentList) {
        String id = (String) document.get("id");
        String title = (String) document.get("title");
        String content = (String) document.get("content");
        String url = (String) document.get("url");

        System.out.println("id "+id+" title"+title+" content"+content+" url"+url);

    }
}

返回javaBean
//返回javaBean的方式
@Test
public void indexSearcherSolrTest02() throws Exception {
//1. 创建 solrServer对象
SolrServer solrServer = new HttpSolrServer(“http://localhost:8080/solr/collection1”);

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

    //3. 获取数据 : 此处有可能会出现转换类型异常的错误:
    List<News> newsList = response.getBeans(News.class);

    for (News news : newsList) {
        System.out.println(news);
    }
}

复杂查询
在创建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]
// solr的复杂查询:
// 提取一个公共的查询方法
public void baseQuery(SolrQuery solrQuery) throws SolrServerException {
//1. 创建solrServer对象
SolrServer solrServer = new HttpSolrServer(“http://localhost:8080/solr/collection1”);

    //2. 执行查询: *:* 查询全部

    QueryResponse response = solrServer.query(solrQuery);

    //3. 解析response
    SolrDocumentList documents = response.getResults();

      List<Product> list = response.getBeans(Product.class);

    for (Product product : list) {
        System.out.println(product);
    }
}

// 多样化的查询:


@Test
public void diversificationTest() throws Exception {
    //1.通配符查询 : ? *
    SolrQuery solrQuery = new SolrQuery("title:el*");
    //2. 相似度查询 : lucene中的模糊查询:
    // 最大编辑次数: 2
    // solr修改最大编辑次数只需要在~后面加上0~2范围即可修改, 如果书写的内容不在这个范围, 使用默认值2
    SolrQuery solrQuery1 = new SolrQuery("content:'lucen~'~2");

    //3. 范围查询:  solr支持 :文本 数值  日期
    // 因为 id字段是一个String类型的, 参考文本的方式的处理, 字典顺序进行展示的
    // 例如: 1,12,2,33,3,44,5,34    [1 TO  3]  1,12,2,3,33,34
    //solr在执行日期查询的时候: solr默认采用的是UTC格式: UTC国际标准时间格式  YYYY-MM-ddThh:mm:ssZ
    // UTC 时间  和   北京 时间 相差 8个小时
   // SolrQuery solrQuery2 = new SolrQuery("id:[1 TO 4]");
    SolrQuery solrQuery2 = new SolrQuery("time:[2018-11-9T05:04:38Z TO 2018-11-10T11:04:38.844Z]");


    //4. 子表达式查询 和 布尔查询
    //  lucene       solr
    //  MUST      :  AND
    //  MUST_NOT  :  NOT
    //  SHOULD    :  OR
    SolrQuery solrQuery3 = new SolrQuery("(id:[1 TO 5] OR content:lucene) OR title:solr");
    publicSearch(solrQuery3);
}

solr的高级
solr的排序
//solr的高级: 排序

@Test
public void sortTest() throws Exception {
    SolrQuery solrQuery = new SolrQuery("*:*");
    solrQuery.setSort("id", SolrQuery.ORDER.asc);
    publicSearch(solrQuery);
}

solr的分页
//solr的高级: 分页处理
@Test
public void limitTest() throws Exception {
int page = 2; //当前页
int pageSize = 3 ;// 每页条数

    SolrQuery solrQuery = new SolrQuery("*:*");
    // 排序
    solrQuery.setSort("id", SolrQuery.ORDER.asc);
    //分页
    solrQuery.setStart((page-1)*pageSize);
    solrQuery.setRows(pageSize);
    publicSearch(solrQuery);
}

solr 的高亮
//solr的高级: 高亮
@Test
public void highlighterTest() throws Exception {
//1. 创建solr的服务对象
SolrServer solrServer = new HttpSolrServer(“http://localhost:8080/solr/collection1”);
int page = 1; //当前页
int pageSize = 3 ;// 每页条数

    SolrQuery solrQuery = new SolrQuery("content:lucene");
    // 排序
    solrQuery.setSort("id", SolrQuery.ORDER.asc);
    //分页
    solrQuery.setStart((page-1)*pageSize);
    solrQuery.setRows(pageSize);

    //高亮:
    solrQuery.setHighlight(true); //开启了高亮
    solrQuery.addHighlightField("content"); //使用add方法来设置高亮字段, 说明高亮字段可以有多个
    solrQuery.addHighlightField("title");
    solrQuery.setHighlightSimplePre("<font color='red'>");
    solrQuery.setHighlightSimplePost("</font>");
    //solrQuery.setHighlightSnippets(1); //设置高亮的分片数

    //2. 执行查询
    QueryResponse response = solrServer.query(solrQuery);
    /*
        最外层的map:
            key:  文档的id
            value: 文档的高亮内容
        内层的map:
            key:  高亮的字段
            value: 这个字段的高亮内容
        list集合: 高亮内容, 而且集合中一般只有一个数据, 除非高亮的字段是一个多值的字段,并且设置高亮的最大分片数大于1
     */
    Map<String, Map<String, List<String>>> map = response.getHighlighting();

    for (String docId : map.keySet()) {
        Map<String, List<String>> listMap = map.get(docId);

        for (String filed : listMap.keySet()) {
            List<String> list = listMap.get(filed);
            System.out.println(list.get(0)+"    "+list.size());
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值