solr服务器搭建起来后, 如果想要使数据加入到Solr服务器中,则在schema.xml中必须要存在与其对应的 Filed 标签声明,当我们添加一个对象时,可以一个一个的setFiled,当Filed较多的时候操作比较麻烦,Solr允许使用javaBean的方式将一个对象直接保存到solr服务器中。solrj 是 solr 的java客户端,用于访问solr索引库。它提供了添加、删除、查询、优化等功能。
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
Java 操作 SolrCloud 与操作 Solr 很类似,主要区别有:
- 连接使用的类不同,连接 Solr 使用的是 HttpSolrClient(springboot使用SolrClient),连接 SolrColud 使用的是 CloudHttp2SolrClient(springboot使用CloudSolrClient)。
- API 针对的操作对象不同,Solr 操作的是 core,SolrCloud 操作的是 collection。
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>
2.2 配置文件
server:
context-path: /
port: 8080
spring:
data:
solr:
# 这里的node1、node2、node3就是solr集群节点名称
zk-host: node1:2181,node2:2181,node3:2181
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的Config配置
CloudSolrClient的java配置类。
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.jmx.support.RegistrationPolicy;
@Configuration
@ComponentScan
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class SolrConfig {
@Value("${solr.zk-host}")
private String zkHost;
@Bean
public CloudSolrClient solrClient() {
CloudSolrClient.Builder builder = new CloudSolrClient.Builder();
builder.withZkHost(zkHost);
CloudSolrClient solrClient = builder.build();
return solrClient;
}
}
2.5 solr基本操作类
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
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;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 使用solrJ 向solr 提交请求,增删改查, solrJ 底层页是发送 http 协议
*/
@Component
public class CloudSolrDAO {
private static Logger logger = LoggerFactory.getLogger(CloudSolrDAO.class);
@Autowired
private CloudSolrClient solrClient;
/**
* 添加动态索引属性(增加/更新文档)
*
* @param collection 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndex(String collection) 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(collection, document);
solrClient.add(collection, document2);
solrClient.commit(collection, true,true);
}
/**
* 通过实体类来添加动态索引属性(增加/更新文档)
*
* @param collection 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndexByBean(String collection) throws SolrServerException, IOException {
PoetInfo info = new PoetInfo("1", 40, "李白", "望庐山瀑布", "字太白", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
solrClient.addBean(collection, info);
solrClient.commit(collection, true,true);
}
/**
* 根据id删除索引
*
* @param collection 索引核心库
* @param id
* @throws SolrServerException
* @throws IOException
*/
public void delIndex(String collection, String id) throws SolrServerException, IOException {
solrClient.deleteById(collection, id);
solrClient.commit(collection, true,true);
}
/**
* 根据名称删除索引
*
* @param collection 索引核心库
* @param name 诗人姓名
* @throws SolrServerException
* @throws IOException
*/
public void delIndexByName(String collection, String name) throws IOException, SolrServerException {
// solrClient.deleteByQuery(collection, "name:杜甫");
solrClient.deleteByQuery(collection, "name:"+name);
solrClient.commit(collection, 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、其他
CloudHttp2SolrClient的方式。
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudHttp2SolrClient;
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;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 使用solrJ 向solr 提交请求,增删改查, solrJ 底层页是发送 http 协议
*/
@Component
public class CloudSolrDAO {
private static Logger logger = LoggerFactory.getLogger(CloudSolrDAO.class);
private CloudHttp2SolrClient solrClient;
@Before
public void before() {
List<String> urls = new ArrayList<>();
urls.add("http://10.40.96.135:8983/solr");
urls.add("http://10.40.96.140:8983/solr");
urls.add("http://10.40.96.144:8983/solr");
solrClient = new CloudHttp2SolrClient.Builder(urls).build();
}
@After
public void after() throws IOException {
solrClient.close();
}
/**
* 添加动态索引属性(增加/更新文档)
*
* @param collection 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndex(String collection) 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(collection, document);
solrClient.add(collection, document2);
solrClient.commit(collection, true, true);
}
/**
* 通过实体类来添加动态索引属性(增加/更新文档)
*
* @param collection 索引核心库
* @throws SolrServerException
* @throws IOException
*/
public void addIndexByBean(String collection) throws SolrServerException, IOException {
PoetInfo info = new PoetInfo("1", 40, "李白", "望庐山瀑布", "字太白", "创造了古代浪漫主义文学高峰、歌行体和七绝达到后人难及的高度");
solrClient.addBean(collection, info);
solrClient.commit(collection, true, true);
}
/**
* 根据id删除索引
*
* @param collection 索引核心库
* @param id
* @throws SolrServerException
* @throws IOException
*/
public void delIndex(String collection, String id) throws SolrServerException, IOException {
solrClient.deleteById(collection, id);
solrClient.commit(collection, true, true);
}
/**
* 根据名称删除索引
*
* @param collection 索引核心库
* @param name 诗人姓名
* @throws SolrServerException
* @throws IOException
*/
public void delIndexByName(String collection, String name) throws IOException, SolrServerException {
// solrClient.deleteByQuery(collection, "name:杜甫");
solrClient.deleteByQuery(collection, "name:" + name);
solrClient.commit(collection, 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());
}
}
}
评论区