solr服务器搭建起来后, 如果想要使数据加入到Solr服务器中,则在schema.xml中必须要存在与其对应的 Filed 标签声明,当我们添加一个对象时,可以一个一个的setFiled,当Filed较多的时候操作比较麻烦,Solr允许使用javaBean的方式将一个对象直接保存到solr服务器中。solrj 是 solr 的java客户端,用于访问solr索引库。它提供了添加、删除、查询、优化等功能。
- Solr单机版安装教程:Linux环境下solr 8.9的下载及安装配置
- Solr集群安装教程:Linux下SolrCloud集群的安装及配置
1、定义 Schema 信息
假设我们需要操作一个描述诗人信息的文档,首先在schema.xml中定义Poet(诗人)对象的具体字段,字段说明如下:
字段 | 描述 |
---|---|
id | 唯一主键 |
age | 年龄 |
name | 姓名 |
poems | 诗歌 |
about | 简介 |
success | 成就 |
定义的 schema 信息如下:
<field name="about" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
<field name="age" type="pint" uninvertible="true" indexed="true" stored="true"/>
<field name="content" type="text_ik" uninvertible="true" indexed="true" stored="true" multiValued="true"/>
<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
<field name="name" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
<field name="poems" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
<field name="success" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
2、springboot整合solr
2.1 引入依赖
solrj是solr的java客户端,用于访问solr索引库。它提供了添加、删除、查询、优化等功能。
springboot引入依赖方式1:
<properties>
<spring.data.solr.version>2.1.1.RELEASE</spring.data.solr.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
<version>${spring.data.solr.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
</dependency>
<!-- 默认 starter 会加载 solrj 进来, 下面这个可以不引-->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>8.9.0</version>
</dependency>
</dependencies>
springboot引入依赖方式2:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
普通java项目引入依赖的方式:
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>8.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-core</artifactId>
<version>8.9.0</version>
</dependency>
2.2 配置文件
server:
context-path: /
port: 8080
spring:
data:
solr:
# 这里的core就是索引核心库的名称,这里也可以不用写core,这时候就需要在代码中使用的时候去指定core,如果是集群,这里的core填写的是collection名称。
# host: http://127.0.0.1:8983/solr 或 http://127.0.0.1:8983/solr/core
host: http://127.0.0.1:8983/solr/core
solr 的 host 可以写成http://127.0.0.1:8983/solr 或 http://127.0.0.1:8983/solr/core ,这里的core就是索引核心库的名称,如果连接的是solr集群,core为需要连接的 collection 名称。(core或collection可以理解为数据库的概念)
2.3 编写实体类
在java中建立实体对象,并且一定要在属性或set方法上添加@Field(nameValue)注解。(org.apache.solr.client.solrj.beans.Field)
import org.apache.solr.client.solrj.beans.Field;
public class PoetInfo {
@Field
private String id;
@Field
private Integer age;
@Field
private String name;
@Field
private String poems;
@Field
private String about;
@Field
private String success;
public PoetInfo() {
}
public PoetInfo(String id, Integer age, String name, String poems, String about, String success) {
this.id = id;
this.age = age;
this.name = name;
this.poems = poems;
this.about = about;
this.success = success;
}
@Override
public String toString() {
return "Info{" +
"id='" + id + '\'' +
", age=" + age +
", name='" + name + '\'' +
", poems='" + poems + '\'' +
", about='" + about + '\'' +
", success='" + success + '\'' +
'}';
}
// getter、setter方法
}
2.4 solr基本操作类
旧版本的连接服务 HttpSolrServer 在solr5版本后已经停用,被新的 HttpSolrClient 取代,具体用法如下。
HttpSolrClient server=new HttpSolrClient(url);
//设置对应请求的目标主机线程数为1000条
server.setDefaultMaxConnectionsPerHost(1000); server.setMaxTotalConnections(10000);
server.setConnectionTimeout(60000);//设置连接超时时间(单位毫秒) 1000
server.setSoTimeout(60000);//// 设置读数据超时时间(单位毫秒) 1000
server.setFollowRedirects(false);//遵循从定向
server.setAllowCompression(true);//允许压缩
上述代码在普通java项目中可以使用,在springboot中可以直接注入 SolrClient 来使用。下面的 SolrDao.java 实现索引的增删改查功能。
2.4.1 增加/更新文档
通过SolrInputDocument 的 添加动态索引属性(增加/更新文档)
/**
* 添加动态索引属性(增加/更新文档)
*
* @param coreName 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndex(String coreName) throws SolrServerException, IOException {
SolrInputDocument document = new SolrInputDocument();
// 默认情况下必须添加的字段,用来区分文档的唯一标识
document.addField("id", "1");
document.addField("age", 30);
document.addField("name", "李白");
document.addField("poems", "望庐山瀑布");
document.addField("about", "字太白");
document.addField("success", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
SolrInputDocument document2 = new SolrInputDocument();
document2.addField("id", "2");
document2.addField("age", 31);
document2.addField("name", "杜甫");
document2.addField("poems", "望岳");
document2.addField("about", "字子美");
document2.addField("success", "唐代伟大的现实主义文学作家,唐诗思想艺术的集大成者");
/*
* 如果spring.data.solr.host 里面配置到 core了, 这里就不需要传 coreName 这个参数了
*/
solrClient.add(coreName, document);
solrClient.add(coreName, document2);
solrClient.commit(coreName, true,true);
}
通过实体类来添加动态索引属性(增加/更新文档)
/**
* 通过实体类来添加动态索引属性(增加/更新文档)
*
* @param coreName 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndexByBean(String coreName) throws SolrServerException, IOException {
PoetInfo info = new PoetInfo("1", 40, "李白", "望庐山瀑布", "字太白", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
solrClient.addBean(coreName, info);
solrClient.commit(coreName, true,true);
}
2.4.2 查询文档
通过 MapSolrParams 查询
/**
* 通过 MapSolrParams 查询
*
* @param coreName 索引核心库
* @throws IOException
* @throws SolrServerException
*/
public void query(String coreName) throws IOException, SolrServerException {
Map<String, String> map = new HashMap<>();
//查询条件
map.put("q", "*:*");
//要显示的内容
map.put("fl", "id,age,name,poems");
//排序方式
map.put("sort", "id asc");
MapSolrParams solrParams = new MapSolrParams(map);
QueryResponse queryResponse = solrClient.query(coreName, solrParams);
SolrDocumentList documents = queryResponse.getResults();
logger.info("查询到{}个文档!", documents.getNumFound());
for (SolrDocument document : documents) {
String id = (String)document.getFieldValue("id");
Integer age = (Integer)document.getFieldValue("age");
String name = (String)document.getFieldValue("name");
String poems = (String)document.getFieldValue("poems");
logger.info("id={},age={},name={},poems={}", id, age, name, poems);
}
}
通过 solrQuery 查询
/**
* 通过 solrQuery 查询
*
* @param coreName 索引核心库
* @throws IOException
* @throws SolrServerException
*/
public void solrQuery(String coreName) throws IOException, SolrServerException {
SolrQuery solrQuery = new SolrQuery("*:*");
solrQuery.addField("id");
solrQuery.addField("age");
solrQuery.addField("name");
solrQuery.addField("poems");
solrQuery.addSort("id", SolrQuery.ORDER.asc);
//设置返回的行数
solrQuery.setRows(10);
QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
SolrDocumentList documents = queryResponse.getResults();
logger.info("查询到{}个文档!", documents.getNumFound());
for (SolrDocument document : documents) {
String id = (String)document.getFieldValue("id");
Integer age = (Integer)document.getFieldValue("age");
String name = (String)document.getFieldValue("name");
String poems = (String)document.getFieldValue("poems");
logger.info("id={},age={},name={},poems={}", id, age, name, poems);
}
}
查询返回实例类对象
/**
* 查询返回实例类对象
*
* @param coreName 索引核心库
* @throws IOException
* @throws SolrServerException
*/
public void solrQueryBean(String coreName) throws IOException, SolrServerException {
SolrQuery solrQuery = new SolrQuery("*:*");
solrQuery.addField("id");
solrQuery.addField("age");
solrQuery.addField("name");
solrQuery.addField("poems");
solrQuery.addField("about");
solrQuery.addField("success");
solrQuery.addSort("id", SolrQuery.ORDER.asc);
//设置返回的行数
solrQuery.setRows(10);
QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
List<PoetInfo> list = queryResponse.getBeans(PoetInfo.class);
logger.info("查询到{}个文档!", list.size());
for (PoetInfo info : list) {
logger.info(info.toString());
}
}
2.4.3 删除文档
根据id删除文档(索引)
/**
* 根据id删除索引
*
* @param coreName 索引核心库
* @param id
* @throws SolrServerException
* @throws IOException
*/
public void delIndex(String coreName, String id) throws SolrServerException, IOException {
solrClient.deleteById(coreName, id);
solrClient.commit(coreName, true,true);
}
根据名称删除文档(索引)
/**
* 根据名称删除索引
*
* @param coreName 索引核心库
* @param name 诗人姓名
* @throws SolrServerException
* @throws IOException
*/
public void delIndexByName(String coreName, String name) throws IOException, SolrServerException {
// solrClient.deleteByQuery(coreName, "name:杜甫");
solrClient.deleteByQuery(coreName, "name:"+name);
solrClient.commit(coreName, true,true);
}
2.4.4 完整代码
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.MapSolrParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 使用solrJ 向solr 提交请求,增删改查, solrJ 底层页是发送 http 协议
*/
@Component
public class SolrDAO {
private static Logger logger = LoggerFactory.getLogger(SolrDAO.class);
@Autowired
private SolrClient solrClient;
/**
* 添加动态索引属性(增加/更新文档)
*
* @param coreName 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndex(String coreName) throws SolrServerException, IOException {
SolrInputDocument document = new SolrInputDocument();
// 默认情况下必须添加的字段,用来区分文档的唯一标识
document.addField("id", "1");
document.addField("age", 30);
document.addField("name", "李白");
document.addField("poems", "望庐山瀑布");
document.addField("about", "字太白");
document.addField("success", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
SolrInputDocument document2 = new SolrInputDocument();
document2.addField("id", "2");
document2.addField("age", 31);
document2.addField("name", "杜甫");
document2.addField("poems", "望岳");
document2.addField("about", "字子美");
document2.addField("success", "唐代伟大的现实主义文学作家,唐诗思想艺术的集大成者");
/*
* 如果spring.data.solr.host 里面配置到 core了, 这里就不需要传 coreName 这个参数了
*/
solrClient.add(coreName, document);
solrClient.add(coreName, document2);
solrClient.commit(coreName, true,true);
}
/**
* 通过实体类来添加动态索引属性(增加/更新文档)
*
* @param coreName 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndexByBean(String coreName) throws SolrServerException, IOException {
PoetInfo info = new PoetInfo("1", 40, "李白", "望庐山瀑布", "字太白", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
solrClient.addBean(coreName, info);
solrClient.commit(coreName, true,true);
}
/**
* 根据id删除索引
*
* @param coreName 索引核心库
* @param id
* @throws SolrServerException
* @throws IOException
*/
public void delIndex(String coreName, String id) throws SolrServerException, IOException {
solrClient.deleteById(coreName, id);
solrClient.commit(coreName, true,true);
}
/**
* 根据名称删除索引
*
* @param coreName 索引核心库
* @param name 诗人姓名
* @throws SolrServerException
* @throws IOException
*/
public void delIndexByName(String coreName, String name) throws IOException, SolrServerException {
// solrClient.deleteByQuery(coreName, "name:杜甫");
solrClient.deleteByQuery(coreName, "name:"+name);
solrClient.commit(coreName, true,true);
}
/**
* 通过 MapSolrParams 查询
*
* @param coreName 索引核心库
* @throws IOException
* @throws SolrServerException
*/
public void query(String coreName) throws IOException, SolrServerException {
Map<String, String> map = new HashMap<>();
//查询条件
map.put("q", "*:*");
//要显示的内容
map.put("fl", "id,age,name,poems");
//排序方式
map.put("sort", "id asc");
MapSolrParams solrParams = new MapSolrParams(map);
QueryResponse queryResponse = solrClient.query(coreName, solrParams);
SolrDocumentList documents = queryResponse.getResults();
logger.info("查询到{}个文档!", documents.getNumFound());
for (SolrDocument document : documents) {
String id = (String)document.getFieldValue("id");
Integer age = (Integer)document.getFieldValue("age");
String name = (String)document.getFieldValue("name");
String poems = (String)document.getFieldValue("poems");
logger.info("id={},age={},name={},poems={}", id, age, name, poems);
}
}
/**
* 通过 solrQuery 查询
*
* @param coreName 索引核心库
* @throws IOException
* @throws SolrServerException
*/
public void solrQuery(String coreName) throws IOException, SolrServerException {
SolrQuery solrQuery = new SolrQuery("*:*");
solrQuery.addField("id");
solrQuery.addField("age");
solrQuery.addField("name");
solrQuery.addField("poems");
solrQuery.addSort("id", SolrQuery.ORDER.asc);
//设置返回的行数
solrQuery.setRows(10);
QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
SolrDocumentList documents = queryResponse.getResults();
logger.info("查询到{}个文档!", documents.getNumFound());
for (SolrDocument document : documents) {
String id = (String)document.getFieldValue("id");
Integer age = (Integer)document.getFieldValue("age");
String name = (String)document.getFieldValue("name");
String poems = (String)document.getFieldValue("poems");
logger.info("id={},age={},name={},poems={}", id, age, name, poems);
}
}
/**
* 查询返回实例类对象
*
* @param coreName 索引核心库
* @throws IOException
* @throws SolrServerException
*/
public void solrQueryBean(String coreName) throws IOException, SolrServerException {
SolrQuery solrQuery = new SolrQuery("*:*");
solrQuery.addField("id");
solrQuery.addField("age");
solrQuery.addField("name");
solrQuery.addField("poems");
solrQuery.addField("about");
solrQuery.addField("success");
solrQuery.addSort("id", SolrQuery.ORDER.asc);
//设置返回的行数
solrQuery.setRows(10);
QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
List<PoetInfo> list = queryResponse.getBeans(PoetInfo.class);
logger.info("查询到{}个文档!", list.size());
for (PoetInfo info : list) {
logger.info(info.toString());
}
}
}
3、其他
HttpSolrClient的方式。
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
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.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.MapSolrParams;
import org.junit.After;
import org.junit.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 使用solrJ 向solr 提交请求,增删改查, solrJ 底层页是发送 http 协议
*/
@Component
public class SolrDAO {
private static Logger logger = LoggerFactory.getLogger(SolrDAO.class);
private HttpSolrClient solrClient;
@Before
public void before() {
solrClient = new HttpSolrClient.Builder("http://10.40.100.69:8983/solr")
.withConnectionTimeout(10000)
.withSocketTimeout(60000)
.build();
}
@After
public void after() throws IOException {
solrClient.close();
}
/**
* 添加动态索引属性(增加/更新文档)
*
* @param coreName 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndex(String coreName) throws SolrServerException, IOException {
SolrInputDocument document = new SolrInputDocument();
// 默认情况下必须添加的字段,用来区分文档的唯一标识
document.addField("id", "1");
document.addField("age", 30);
document.addField("name", "李白");
document.addField("poems", "望庐山瀑布");
document.addField("about", "字太白");
document.addField("success", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
SolrInputDocument document2 = new SolrInputDocument();
document2.addField("id", "2");
document2.addField("age", 31);
document2.addField("name", "杜甫");
document2.addField("poems", "望岳");
document2.addField("about", "字子美");
document2.addField("success", "唐代伟大的现实主义文学作家,唐诗思想艺术的集大成者");
/*
* 如果spring.data.solr.host 里面配置到 core了, 这里就不需要传 coreName 这个参数了
*/
solrClient.add(coreName, document);
solrClient.add(coreName, document2);
solrClient.commit(coreName, true,true);
}
/**
* 通过实体类来添加动态索引属性(增加/更新文档)
*
* @param coreName 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndexByBean(String coreName) throws SolrServerException, IOException {
PoetInfo info = new PoetInfo("1", 40, "李白", "望庐山瀑布", "字太白", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
solrClient.addBean(coreName, info);
solrClient.commit(coreName, true,true);
}
/**
* 根据id删除索引
*
* @param coreName 索引核心库
* @param id
* @throws SolrServerException
* @throws IOException
*/
public void delIndex(String coreName, String id) throws SolrServerException, IOException {
solrClient.deleteById(coreName, id);
solrClient.commit(coreName, true,true);
}
/**
* 根据名称删除索引
*
* @param coreName 索引核心库
* @param name 诗人姓名
* @throws SolrServerException
* @throws IOException
*/
public void delIndexByName(String coreName, String name) throws IOException, SolrServerException {
// solrClient.deleteByQuery(coreName, "name:杜甫");
solrClient.deleteByQuery(coreName, "name:"+name);
solrClient.commit(coreName, true,true);
}
/**
* 通过 MapSolrParams 查询
*
* @param coreName 索引核心库
* @throws IOException
* @throws SolrServerException
*/
public void query(String coreName) throws IOException, SolrServerException {
Map<String, String> map = new HashMap<>();
//查询条件
map.put("q", "*:*");
//要显示的内容
map.put("fl", "id,age,name,poems");
//排序方式
map.put("sort", "id asc");
MapSolrParams solrParams = new MapSolrParams(map);
QueryResponse queryResponse = solrClient.query(coreName, solrParams);
SolrDocumentList documents = queryResponse.getResults();
logger.info("查询到{}个文档!", documents.getNumFound());
for (SolrDocument document : documents) {
String id = (String)document.getFieldValue("id");
Integer age = (Integer)document.getFieldValue("age");
String name = (String)document.getFieldValue("name");
String poems = (String)document.getFieldValue("poems");
logger.info("id={},age={},name={},poems={}", id, age, name, poems);
}
}
/**
* 通过 solrQuery 查询
*
* @param coreName 索引核心库
* @throws IOException
* @throws SolrServerException
*/
public void solrQuery(String coreName) throws IOException, SolrServerException {
SolrQuery solrQuery = new SolrQuery("*:*");
solrQuery.addField("id");
solrQuery.addField("age");
solrQuery.addField("name");
solrQuery.addField("poems");
solrQuery.addSort("id", SolrQuery.ORDER.asc);
//设置返回的行数
solrQuery.setRows(10);
QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
SolrDocumentList documents = queryResponse.getResults();
logger.info("查询到{}个文档!", documents.getNumFound());
for (SolrDocument document : documents) {
String id = (String)document.getFieldValue("id");
Integer age = (Integer)document.getFieldValue("age");
String name = (String)document.getFieldValue("name");
String poems = (String)document.getFieldValue("poems");
logger.info("id={},age={},name={},poems={}", id, age, name, poems);
}
}
/**
* 查询返回实例类对象
*
* @param coreName 索引核心库
* @throws IOException
* @throws SolrServerException
*/
public void solrQueryBean(String coreName) throws IOException, SolrServerException {
SolrQuery solrQuery = new SolrQuery("*:*");
solrQuery.addField("id");
solrQuery.addField("age");
solrQuery.addField("name");
solrQuery.addField("poems");
solrQuery.addField("about");
solrQuery.addField("success");
solrQuery.addSort("id", SolrQuery.ORDER.asc);
//设置返回的行数
solrQuery.setRows(10);
QueryResponse queryResponse = solrClient.query(coreName, solrQuery);
List<PoetInfo> list = queryResponse.getBeans(PoetInfo.class);
logger.info("查询到{}个文档!", list.size());
for (PoetInfo info : list) {
logger.info(info.toString());
}
}
}
评论区