简介

SolrJ是一个API,它使用Java(或任何基于JVM的语言)编写的应用程序可以轻松地与Solr交谈。SolrJ隐藏了许多连接到Solr的细节,并允许您的应用程序通过简单的高级方法与Solr交互。SolrJ支持大多数Solr API,并且具有高度可配置性。
官方API参考文档: https://lucene.apache.org/solr/guide

  • 工程搭建

pom.xml依赖:

  1. <dependency>
  2. <groupId>org.apache.solr</groupId>
  3. <artifactId>solr-solrj</artifactId>
  4. <version>7.7.2</version>
  5. </dependency>

注意:如果不用maven构建项目,只需要将solr-solrj-*.jar和在dist/solrj-lib目录中的依赖包放入到工程中。

SolrJ连接

1. HttpSolrClient(单机Solr)

SolrClient是一个抽象类,下边有很多被实现的子类,如:“HttpSolrClient”(面向以查询为中心的工作负载) ,但也是一个很好的通用客户端。直接与单个Solr节点通信。不同solr版本solrj 的创建方式有所不同。

  1. // solr4创建方式
  2. SolrServer solrServer = new HttpSolrServer(solrUrl);
  3. // solr5创建方式,在url中指定core名称:core1
  4. HttpSolrClient solrClient = new HttpSolrClient(solrUrl);
  5. // solr7创建方式,在url中指定core名称:core1
  6. HttpSolrClient solrClient = new HttpSolrClient.Builder(solrUrl).build();

示例:

  1. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  2. /****
  3. * @Description 连接Solr,使用运行中的某一台solr节点
  4. */
  5. public class Test01Connection {
  6. // 声明一个连接solr的地址(ip:port/solr/库名)
  7. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  8. // 声明一个连接solr的对象
  9. private static HttpSolrClient httpSolrClient;
  10. static {
  11. // 创建solrClient同时指定超时时间,不指定走默认配置
  12. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL)
  13. .withConnectionTimeout(10000)
  14. .withSocketTimeout(60000)
  15. .build();
  16. }
  17. public static void main(String[] args) {
  18. System.out.println(httpSolrClient);
  19. }
  20. }

2. CloudSolrClient(Solr集群)

CloudSolrClient(面向与SolrCloud部署的通信),使用已记录的ZooKeeper状态来发现并将请求路由到健康的Solr节点。有两种不同的接入方式,第一种方式:使用运行中的某一台solr节点;第二种方式:使用zookeeper节点连接(推荐)

通过Solr URL连接集群

  1. import org.apache.solr.client.solrj.SolrQuery;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.CloudSolrClient;
  4. import org.apache.solr.client.solrj.response.QueryResponse;
  5. import org.apache.solr.common.SolrDocument;
  6. import org.apache.solr.common.SolrDocumentList;
  7. import java.io.IOException;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. /****
  11. * @Description 全查询
  12. */
  13. public class Test14SolrCloudQueryAll {
  14. // 声明一个连接solr的对象
  15. private static CloudSolrClient cloudSolrClient;
  16. static {
  17. List<String> solrUrls = new ArrayList<>();
  18. solrUrls.add("http://ltsr003:8983/solr");
  19. solrUrls.add("http://ltsr005:8983/solr");
  20. solrUrls.add("http://ltsr006:8983/solr");
  21. cloudSolrClient = new CloudSolrClient.Builder(solrUrls).build();
  22. cloudSolrClient.setDefaultCollection("db_sync");
  23. }
  24. public static void main(String[] args) throws IOException, SolrServerException {
  25. String keywords = "*:*";
  26. // 创建一个查询条件对象
  27. SolrQuery solrQuery = new SolrQuery(keywords);
  28. // 查询
  29. QueryResponse query = cloudSolrClient.query(solrQuery);
  30. // 取出结果
  31. SolrDocumentList results = query.getResults();
  32. System.out.println("总条数:" + results.getNumFound());
  33. for (SolrDocument result : results) {
  34. System.out.println(result);
  35. }
  36. }
  37. }

通过ZooKeeper连接集群(推荐)

  1. import org.apache.solr.client.solrj.SolrQuery;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.CloudSolrClient;
  4. import org.apache.solr.client.solrj.response.QueryResponse;
  5. import org.apache.solr.common.SolrDocument;
  6. import org.apache.solr.common.SolrDocumentList;
  7. import java.io.IOException;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. import java.util.Optional;
  11. /****
  12. * @Description 全查询(zk)
  13. */
  14. public class Test15SolrCloudQueryAll {
  15. // 声明一个连接solr的对象
  16. private static CloudSolrClient cloudSolrClient;
  17. static {
  18. List<String> zkHosts = new ArrayList<>();
  19. zkHosts.add("192.168.0.15:2181");
  20. zkHosts.add("192.168.0.16:2181");
  21. zkHosts.add("192.168.0.17:2181");
  22. cloudSolrClient = new CloudSolrClient.Builder(zkHosts, Optional.empty()).build();
  23. cloudSolrClient.setDefaultCollection("db_sync");
  24. cloudSolrClient.setZkClientTimeout(5000);
  25. cloudSolrClient.setZkConnectTimeout(5000);
  26. }
  27. public static void main(String[] args) throws IOException, SolrServerException {
  28. String keywords = "*:*";
  29. // 创建一个查询条件对象
  30. SolrQuery solrQuery = new SolrQuery(keywords);
  31. // 查询
  32. QueryResponse query = cloudSolrClient.query(solrQuery);
  33. // 取出结果
  34. SolrDocumentList results = query.getResults();
  35. System.out.println("总条数:" + results.getNumFound());
  36. for (SolrDocument result : results) {
  37. System.out.println(result);
  38. }
  39. cloudSolrClient.close();
  40. }
  41. }

案例

01. 新增数据

1. 新增单条记录

  1. import org.apache.solr.client.solrj.SolrServerException;
  2. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  3. import org.apache.solr.common.SolrInputDocument;
  4. import java.io.IOException;
  5. /***
  6. * @Description 新增数据(单条) <br/>
  7. * 创建索引库:<br/>
  8. * https://www.yuque.com/polaris-docs/bigdata/solr-op
  9. * {
  10. * "id":"1",
  11. * "content_id":10,
  12. * "title":"我是中国人",
  13. * "content":"作为一个中国人,我感到很自豪。",
  14. * "type":1,
  15. * "create_at":1578912614123,
  16. * "publish_at":1578912614123
  17. * }
  18. */
  19. public class Test02AddRecord {
  20. // 声明一个连接solr的地址(ip:port/solr/库名)
  21. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  22. // 声明一个连接solr的对象
  23. private static HttpSolrClient httpSolrClient;
  24. static {
  25. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  26. }
  27. public static void main(String[] args) throws IOException, SolrServerException {
  28. addOneByOne();
  29. }
  30. private static void addOneByOne() throws SolrServerException, IOException {
  31. // 一个个添加
  32. SolrInputDocument doc = new SolrInputDocument();
  33. // id不给值将自动生成UUID
  34. doc.addField("id", 2);
  35. doc.addField("content_id", 101L);
  36. doc.addField("title", "我是中国人,打到小日本");
  37. doc.addField("content", "作为一个中国人,我感到很自豪。");
  38. doc.addField("type", 1);
  39. doc.addField("create_at", 1578912614123L);
  40. doc.addField("publish_at", 1578912614123L);
  41. httpSolrClient.add(doc);
  42. httpSolrClient.commit();
  43. httpSolrClient.close();
  44. System.out.println("操作成功");
  45. }
  46. }

2. 新增多条记录

■ 文档对象列表方式(List

  1. import org.apache.solr.client.solrj.SolrServerException;
  2. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  3. import org.apache.solr.common.SolrInputDocument;
  4. import java.io.IOException;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. /***
  8. * @Description 新增数据(批量) <br/>
  9. * 创建索引库:<br/>
  10. * https://www.yuque.com/polaris-docs/bigdata/solr-op
  11. * {
  12. * "id":"1",
  13. * "content_id":10,
  14. * "title":"我是中国人",
  15. * "content":"作为一个中国人,我感到很自豪。",
  16. * "type":1,
  17. * "create_at":1578912614123,
  18. * "publish_at":1578912614123
  19. * }
  20. */
  21. public class Test04AddRecords {
  22. // 声明一个连接solr的地址(ip:port/solr/库名)
  23. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  24. // 声明一个连接solr的对象
  25. private static HttpSolrClient httpSolrClient;
  26. static {
  27. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  28. }
  29. public static void main(String[] args) throws IOException, SolrServerException {
  30. addByList();
  31. }
  32. private static void addByList() throws SolrServerException, IOException {
  33. // 一个集合一个集合的添加
  34. List<SolrInputDocument> docs = new ArrayList<>();
  35. for (int i = 199; i <= 204; i++) {
  36. SolrInputDocument doc = new SolrInputDocument();
  37. // id不给值将自动生成UUID
  38. doc.addField("id", i);
  39. doc.addField("content_id", i * 10L);
  40. doc.addField("title", "我是中国人,打倒小日本" + i);
  41. doc.addField("content", "作为一个中国人,我感到很自豪。");
  42. doc.addField("type", 1);
  43. doc.addField("create_at", 1578912614123L);
  44. doc.addField("publish_at", 1578912614123L);
  45. docs.add(doc);
  46. }
  47. httpSolrClient.add(docs);
  48. httpSolrClient.commit();
  49. httpSolrClient.close();
  50. System.out.println("操作成功");
  51. }
  52. }

注解方式(Pojo Annotation)

  1. package com.lonton.bigdata.pojo;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import org.apache.solr.client.solrj.beans.Field;
  6. /**
  7. * @author polaris <450733605@qq.com>
  8. * Description Pojo-文章类
  9. * Date 2020-8-19 20:13
  10. * Version 1.0.0
  11. */
  12. @Data
  13. @AllArgsConstructor
  14. @NoArgsConstructor
  15. public class Article {
  16. @Field("id")
  17. private Integer id;
  18. @Field("content_id")
  19. private Long contentId;
  20. @Field("title")
  21. private String title;
  22. @Field("content")
  23. private String content;
  24. @Field("type")
  25. private Integer type;
  26. @Field("create_at")
  27. private Long createAt;
  28. @Field("publish_at")
  29. private Long publishAt;
  30. @Override
  31. public String toString() {
  32. return "Article{" +
  33. "id=" + id +
  34. ", contentId=" + contentId +
  35. ", title='" + title + '\'' +
  36. ", content='" + content + '\'' +
  37. ", type=" + type +
  38. ", createAt=" + createAt +
  39. ", publishAt=" + publishAt +
  40. '}';
  41. }
  42. }
  1. import com.lonton.bigdata.pojo.Article;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  4. import java.io.IOException;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. /***
  8. * @Description 新增数据(注解方式) <br/>
  9. * 创建索引库:<br/>
  10. * https://www.yuque.com/polaris-docs/bigdata/solr-op
  11. * {
  12. * "id":"1",
  13. * "content_id":10,
  14. * "title":"我是中国人",
  15. * "content":"作为一个中国人,我感到很自豪。",
  16. * "type":1,
  17. * "create_at":1578912614123,
  18. * "publish_at":1578912614123
  19. * }
  20. */
  21. public class Test05AddRecordsAnnotation {
  22. // 声明一个连接solr的地址(ip:port/solr/库名)
  23. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  24. // 声明一个连接solr的对象
  25. private static HttpSolrClient httpSolrClient;
  26. static {
  27. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  28. }
  29. public static void main(String[] args) throws IOException, SolrServerException {
  30. List<Article> pojo = new ArrayList<>(5);
  31. for (int i = 205; i <= 235; i++) {
  32. pojo.add(new Article(i, i * 10L, "我是中国人,打倒小日本" + i, "作为一个中国人,我感到很自豪。", 1, 1578912614123L, 1578912614123L));
  33. }
  34. httpSolrClient.addBeans(pojo);
  35. httpSolrClient.commit();
  36. httpSolrClient.close();
  37. System.out.println("操作成功");
  38. }
  39. }

02. 删除数据

  1. package com.lonton.bigdata.solr;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  4. import java.io.IOException;
  5. import java.util.Arrays;
  6. public class Test03DeleteRecords {
  7. // 声明一个连接solr的地址(ip:port/solr/库名)
  8. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  9. // 声明一个连接solr的对象
  10. private static HttpSolrClient httpSolrClient;
  11. static {
  12. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  13. }
  14. public static void main(String[] args) throws IOException, SolrServerException {
  15. // 方式1:根据ID删除(单行)
  16. httpSolrClient.deleteById("1");
  17. // 方式2:根据ID的集合删除(单行/多行)
  18. httpSolrClient.deleteById(Arrays.asList("199", "200", "201"));
  19. // 方式3:根据查询结果删除(单行/多行)
  20. // 示例:全部删除
  21. httpSolrClient.deleteByQuery("*:*");
  22. httpSolrClient.commit();
  23. httpSolrClient.close();
  24. System.out.println("操作成功");
  25. }
  26. }

03. 查询数据

1. 全表扫描

  1. import org.apache.solr.client.solrj.SolrQuery;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  4. import org.apache.solr.client.solrj.response.QueryResponse;
  5. import org.apache.solr.common.SolrDocument;
  6. import org.apache.solr.common.SolrDocumentList;
  7. import java.io.IOException;
  8. /****
  9. * @Description 全表扫描
  10. */
  11. public class Test06QueryAll {
  12. // 声明一个连接solr的地址(ip:port/solr/库名)
  13. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  14. // 声明一个连接solr的对象
  15. private static HttpSolrClient httpSolrClient;
  16. static {
  17. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  18. }
  19. public static void main(String[] args) throws IOException, SolrServerException {
  20. String keywords = "*:*";
  21. // 创建一个查询条件对象
  22. SolrQuery solrQuery = new SolrQuery(keywords);
  23. // 查询
  24. QueryResponse query = httpSolrClient.query(solrQuery);
  25. // 取出结果
  26. SolrDocumentList results = query.getResults();
  27. System.out.println("总条数:" + results.getNumFound());
  28. for (SolrDocument result : results) {
  29. System.out.println(result);
  30. }
  31. }
  32. }

2. 分页查询

  1. import org.apache.solr.client.solrj.SolrQuery;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  4. import org.apache.solr.client.solrj.response.QueryResponse;
  5. import org.apache.solr.common.SolrDocument;
  6. import org.apache.solr.common.SolrDocumentList;
  7. import java.io.IOException;
  8. /****
  9. * @Description 分页查询
  10. */
  11. public class Test07QueryForPage {
  12. // 声明一个连接solr的地址(ip:port/solr/库名)
  13. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  14. // 声明一个连接solr的对象
  15. private static HttpSolrClient httpSolrClient;
  16. static {
  17. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  18. }
  19. public static void main(String[] args) throws IOException, SolrServerException {
  20. String keywords = "*:*";
  21. // 创建一个查询条件对象
  22. SolrQuery solrQuery = new SolrQuery(keywords);
  23. int page = 2; // 第2页
  24. int limit = 2; // 每页显示条数
  25. solrQuery.setStart((page - 1) * limit); // 设置从哪里开始查,不查页码
  26. solrQuery.setRows(limit); // 设置每页显示多少条
  27. // 查询
  28. QueryResponse query = httpSolrClient.query(solrQuery);
  29. // 取出结果
  30. SolrDocumentList results = query.getResults();
  31. System.out.println("总条数:" + results.getNumFound());
  32. for (SolrDocument result : results) {
  33. System.out.println(result);
  34. }
  35. }
  36. }

3. 排序

  1. import org.apache.solr.client.solrj.SolrQuery;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  4. import org.apache.solr.client.solrj.response.QueryResponse;
  5. import org.apache.solr.common.SolrDocument;
  6. import org.apache.solr.common.SolrDocumentList;
  7. import java.io.IOException;
  8. /****
  9. * @Description 排序
  10. */
  11. public class Test08QuerySort {
  12. // 声明一个连接solr的地址(ip:port/solr/库名)
  13. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  14. // 声明一个连接solr的对象
  15. private static HttpSolrClient httpSolrClient;
  16. static {
  17. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  18. }
  19. public static void main(String[] args) throws IOException, SolrServerException {
  20. String keywords = "*:*";
  21. // 创建一个查询条件对象
  22. SolrQuery solrQuery = new SolrQuery(keywords);
  23. // 只能根据一个属性进行排序
  24. solrQuery.setSort("id", SolrQuery.ORDER.desc);
  25. // 查询
  26. QueryResponse query = httpSolrClient.query(solrQuery);
  27. // 取出结果
  28. SolrDocumentList results = query.getResults();
  29. System.out.println("总条数:" + results.getNumFound());
  30. for (SolrDocument result : results) {
  31. System.out.println(result);
  32. }
  33. }
  34. }

4. 高亮显示

  1. import com.lonton.bigdata.pojo.Article;
  2. import org.apache.solr.client.solrj.SolrQuery;
  3. import org.apache.solr.client.solrj.SolrServerException;
  4. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  5. import org.apache.solr.client.solrj.response.QueryResponse;
  6. import org.apache.solr.common.SolrDocument;
  7. import org.apache.solr.common.SolrDocumentList;
  8. import org.apache.solr.common.StringUtils;
  9. import java.io.IOException;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.util.Map;
  13. /****
  14. * @Description 高亮显示
  15. */
  16. public class Test09QueryHeightLight {
  17. // 声明一个连接solr的地址(ip:port/solr/库名)
  18. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  19. // 声明一个连接solr的对象
  20. private static HttpSolrClient httpSolrClient;
  21. static {
  22. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  23. }
  24. public static void main(String[] args) throws IOException, SolrServerException {
  25. List<Article> articleList = new ArrayList<>();
  26. String keywords = "title:中国人";
  27. // 创建一个查询条件对象
  28. SolrQuery solrQuery = new SolrQuery(keywords);
  29. // 开户高亮
  30. solrQuery.setHighlight(true);
  31. // 设置要进行高亮的属性
  32. solrQuery.addHighlightField("title");
  33. solrQuery.addHighlightField("content");
  34. // 设置高亮的前后缀
  35. solrQuery.setHighlightSimplePre("<font color=red>");
  36. solrQuery.setHighlightSimplePost("</font>");
  37. // 查询
  38. QueryResponse query = httpSolrClient.query(solrQuery);
  39. // 取出结果
  40. SolrDocumentList results = query.getResults();
  41. // 取出高亮的结果
  42. Map<String, Map<String, List<String>>> highlighting = query.getHighlighting();
  43. System.out.println("总条数:" + results.getNumFound());
  44. for (SolrDocument result : results) { // 搜索处理的每个文档,进文档里面的内容进行高亮
  45. Article pojo = new Article();
  46. pojo.setId(Integer.valueOf(result.getFieldValue("id").toString()));
  47. pojo.setContentId(Long.valueOf(result.getFieldValue("content_id").toString()));
  48. pojo.setTitle(result.getFieldValue("title").toString());
  49. pojo.setContent(result.getFieldValue("content").toString());
  50. pojo.setType(Integer.valueOf(result.getFieldValue("type").toString()));
  51. pojo.setCreateAt(Long.valueOf(result.getFieldValue("create_at").toString()));
  52. pojo.setPublishAt(Long.valueOf(result.getFieldValue("publish_at").toString()));
  53. String id = (String) result.getFieldValue("id");
  54. Map<String, List<String>> listMap = highlighting.get(id);
  55. if (null != listMap && !listMap.isEmpty()) {
  56. List<String> title = listMap.get("title");
  57. List<String> content = listMap.get("content");
  58. if (title != null && !StringUtils.isEmpty(title.get(0))) {
  59. pojo.setTitle(title.get(0));
  60. }
  61. if (content != null && !StringUtils.isEmpty(content.get(0))) {
  62. pojo.setContent(content.get(0));
  63. }
  64. }
  65. articleList.add(pojo);
  66. }
  67. for (Article article : articleList) {
  68. System.out.println(article);
  69. }
  70. }
  71. }

5. 范围查询

  1. import org.apache.solr.client.solrj.SolrQuery;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  4. import org.apache.solr.client.solrj.response.QueryResponse;
  5. import org.apache.solr.common.SolrDocument;
  6. import org.apache.solr.common.SolrDocumentList;
  7. import java.io.IOException;
  8. /****
  9. * @Description 范围查询
  10. */
  11. public class Test10QueryRange {
  12. // 声明一个连接solr的地址(ip:port/solr/库名)
  13. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  14. // 声明一个连接solr的对象
  15. private static HttpSolrClient httpSolrClient;
  16. static {
  17. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  18. }
  19. public static void main(String[] args) throws IOException, SolrServerException {
  20. // 创建条件
  21. SolrQuery solrQuery = new SolrQuery("*:*");
  22. // 限定范围(<=?)
  23. solrQuery.setFilterQueries("id:[* TO 205]");
  24. // 限定范围(>=? and <=?)
  25. solrQuery.setFilterQueries("id:[205 TO 207]");
  26. // 限定范围(>=?)
  27. solrQuery.setFilterQueries("id:[207 TO *]");
  28. QueryResponse query = httpSolrClient.query(solrQuery);
  29. // 取出结果
  30. SolrDocumentList results = query.getResults();
  31. System.out.println("总条数:" + results.getNumFound());
  32. for (SolrDocument result : results) {
  33. System.out.println(result);
  34. }
  35. }
  36. }

6. 过滤

  1. import org.apache.solr.client.solrj.SolrQuery;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  4. import org.apache.solr.client.solrj.response.QueryResponse;
  5. import org.apache.solr.common.SolrDocument;
  6. import org.apache.solr.common.SolrDocumentList;
  7. import java.io.IOException;
  8. /****
  9. * @Description 过滤查询
  10. */
  11. public class Test11QueryFilter {
  12. // 声明一个连接solr的地址(ip:port/solr/库名)
  13. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  14. // 声明一个连接solr的对象
  15. private static HttpSolrClient httpSolrClient;
  16. static {
  17. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  18. }
  19. public static void main(String[] args) throws IOException, SolrServerException {
  20. // 创建条件
  21. SolrQuery solrQuery = new SolrQuery("*:*");
  22. // 限定条件 id=205
  23. solrQuery.setFilterQueries("id:205");
  24. QueryResponse query = httpSolrClient.query(solrQuery);
  25. // 取出结果
  26. SolrDocumentList results = query.getResults();
  27. System.out.println("总条数:" + results.getNumFound());
  28. for (SolrDocument result : results) {
  29. System.out.println(result);
  30. }
  31. }
  32. }

7. 关键字查询(复制域-copyField

  1. import org.apache.solr.client.solrj.SolrQuery;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  4. import org.apache.solr.client.solrj.response.QueryResponse;
  5. import org.apache.solr.common.SolrDocument;
  6. import org.apache.solr.common.SolrDocumentList;
  7. import java.io.IOException;
  8. /****
  9. * @author polaris <450733605@qq.com>
  10. * @Description 关键字查询(复制域) <br/>
  11. * 注意:修改Schema后,新增的数据才能通过关键字查询
  12. * <field name="title" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
  13. * <field name="content" type="text_ik" uninvertible="true" indexed="true" stored="true"/>
  14. * <field name="keywords" type="text_ik" uninvertible="false" multiValued="true" indexed="true" stored="true"/>
  15. * <copyField source="title" dest="keywords"/>
  16. * <copyField source="content" dest="keywords"/>
  17. */
  18. public class Test12QueryKeywords {
  19. // 声明一个连接solr的地址(ip:port/solr/库名)
  20. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  21. // 声明一个连接solr的对象
  22. private static HttpSolrClient httpSolrClient;
  23. static {
  24. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  25. }
  26. public static void main(String[] args) throws IOException, SolrServerException {
  27. // 创建条件
  28. SolrQuery solrQuery = new SolrQuery("keywords:中国");
  29. QueryResponse query = httpSolrClient.query(solrQuery);
  30. // 取出结果
  31. SolrDocumentList results = query.getResults();
  32. System.out.println("总条数:" + results.getNumFound());
  33. for (SolrDocument result : results) {
  34. System.out.println(result);
  35. }
  36. }
  37. }

注意:修改**Schema**后,新增的数据才能通过关键字查询。

8. 综合查询

  1. import org.apache.solr.client.solrj.SolrQuery;
  2. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  3. import org.apache.solr.client.solrj.response.QueryResponse;
  4. import org.apache.solr.common.SolrDocument;
  5. import org.apache.solr.common.SolrDocumentList;
  6. import org.apache.solr.common.StringUtils;
  7. import java.util.ArrayList;
  8. import java.util.HashMap;
  9. import java.util.List;
  10. import java.util.Map;
  11. /****
  12. * @Description 综合查询
  13. */
  14. public class Test13QueryComprehensive {
  15. // 声明一个连接solr的地址(ip:port/solr/库名)
  16. public static final String SOLR_URL = "http://bigdata-node1:8983/solr/db_sync";
  17. // 声明一个连接solr的对象
  18. private static HttpSolrClient httpSolrClient;
  19. static {
  20. httpSolrClient = new HttpSolrClient.Builder(SOLR_URL).build();
  21. }
  22. public static void main(String[] args) {
  23. Map<String, String> filter = new HashMap<>();
  24. filter.put("id", "205");
  25. List<Map<String, Object>> list = queryAll("中国", 1, 10, 1, "205-209", filter);
  26. for (Map<String, Object> map : list) {
  27. System.out.println(map);
  28. }
  29. }
  30. /***
  31. * @Description: 综合查询
  32. * @Param:
  33. * [
  34. * keywords, 关键字
  35. * page, 页码
  36. * limit, 每页条数
  37. * sort, 排序规则:1-升;0-降序
  38. * range, 范围 start-end
  39. * filter 过滤条件
  40. * ]
  41. * @return
  42. */
  43. public static List<Map<String, Object>> queryAll(String keywords, int page, int limit, int sort, String range, Map<String, String> filter) {
  44. // 条件构造
  45. SolrQuery solrQuery = new SolrQuery("keywords:" + keywords);
  46. // 分页处理
  47. solrQuery.setStart((page - 1) * limit);
  48. solrQuery.setRows(limit);
  49. // 排序
  50. switch (sort) {
  51. case 0:
  52. solrQuery.addSort("id", SolrQuery.ORDER.desc);
  53. break;
  54. case 1:
  55. solrQuery.addSort("id", SolrQuery.ORDER.asc);
  56. break;
  57. }
  58. // 范围和过滤条件的处理
  59. List<String> fqList = new ArrayList<>();
  60. if (!StringUtils.isEmpty(range)) {
  61. if (!range.contains("-")) {
  62. throw new RuntimeException("范围参数不合法");
  63. }
  64. String[] split = range.split("-");
  65. fqList.add("id:[" + split[0] + " TO " + split[1] + "]");
  66. }
  67. if (filter != null && !filter.isEmpty()) {
  68. filter.forEach((k, v) -> {
  69. fqList.add(k + ":" + v);
  70. });
  71. }
  72. if (!fqList.isEmpty()) {
  73. solrQuery.setFilterQueries(fqList.toArray(new String[]{}));
  74. }
  75. // 处理高亮
  76. // 设置要进行高亮的属性
  77. solrQuery.addHighlightField("title");
  78. solrQuery.addHighlightField("content");
  79. // 设置高亮的前后缀
  80. solrQuery.setHighlightSimplePre("<font color=red>");
  81. solrQuery.setHighlightSimplePost("</font>");
  82. try {
  83. List<Map<String, Object>> listMaps = new ArrayList<>();
  84. QueryResponse query = httpSolrClient.query(solrQuery);
  85. SolrDocumentList results = query.getResults();
  86. Map<String, Map<String, List<String>>> highlighting = query.getHighlighting();
  87. System.out.println("总条数:" + results.getNumFound());
  88. for (SolrDocument result : results) {
  89. Map<String, Object> map = new HashMap<>();
  90. map.put("id", result.getFieldValue("id"));
  91. map.put("content_id", result.getFieldValue("content_id"));
  92. map.put("title", result.getFieldValue("title"));
  93. map.put("content", result.getFieldValue("content"));
  94. map.put("type", result.getFieldValue("type"));
  95. map.put("create_at", result.getFieldValue("create_at"));
  96. map.put("publish_at", result.getFieldValue("publish_at"));
  97. Map<String, List<String>> listMap = highlighting.get(map.get("id"));
  98. if (null != listMap && !listMap.isEmpty()) {
  99. String title = listMap.get("title").get(0);
  100. String content = listMap.get("content").get(0);
  101. map.put("title", title);
  102. map.put("content", content);
  103. }
  104. listMaps.add(map);
  105. }
  106. return listMaps;
  107. } catch (Exception e) {
  108. e.printStackTrace();
  109. }
  110. return null;
  111. }
  112. }

SolrJ API

■ 常量类(Constant.java)

  1. public class Constant {
  2. /** Solr配置 **/
  3. public static class SolrConfig {
  4. public final static String SOLR_URL="http://bigdata-node1:8983/solr/db_sync";
  5. }
  6. }

■ 工具类(SolrUtil.java)

  1. import java.io.IOException;
  2. import java.lang.reflect.Field;
  3. import java.util.*;
  4. import com.lonton.bigdata.constant.Constant;
  5. import org.apache.commons.beanutils.BeanUtils;
  6. import org.apache.solr.client.solrj.SolrQuery;
  7. import org.apache.solr.client.solrj.SolrServerException;
  8. import org.apache.solr.client.solrj.beans.DocumentObjectBinder;
  9. import org.apache.solr.client.solrj.impl.HttpSolrClient;
  10. import org.apache.solr.client.solrj.response.QueryResponse;
  11. import org.apache.solr.client.solrj.response.UpdateResponse;
  12. import org.apache.solr.common.SolrDocument;
  13. import org.apache.solr.common.SolrDocumentList;
  14. import org.apache.solr.common.SolrInputDocument;
  15. import org.slf4j.Logger;
  16. import org.slf4j.LoggerFactory;
  17. public class SolrUtil {
  18. private static final Logger log = LoggerFactory.getLogger(SolrUtil.class);
  19. // 声明一个连接solr的对象
  20. private static HttpSolrClient client;
  21. static {
  22. // SolrJ-7.x版本连接Solr
  23. client = new HttpSolrClient.Builder(Constant.SolrConfig.SOLR_URL).build();
  24. // SolrJ-5.x版本连接Solr
  25. //client = new HttpSolrClient(Constant.SolrConfig.SOLR_URL);
  26. }
  27. /**
  28. * 将Map对象添加到Solr中
  29. *
  30. * @param map Map对象
  31. * @return
  32. */
  33. public static boolean add(Map map) {
  34. Set kSet = map.keySet();
  35. SolrInputDocument doc = new SolrInputDocument();
  36. for (Object k : kSet) {
  37. Object val = map.get(k);
  38. if (val != null) {
  39. doc.addField(k.toString(), val);
  40. }
  41. }
  42. try {
  43. client.add(doc);
  44. UpdateResponse resp = client.commit();
  45. if (resp.getStatus() == 0) {
  46. log.debug("add successfully!");
  47. return true;
  48. }
  49. } catch (Exception e) {
  50. log.error(e.getMessage());
  51. e.printStackTrace();
  52. }
  53. log.debug("add failure!");
  54. return false;
  55. }
  56. /**
  57. * 通过文档ID删除Solr中的文档
  58. *
  59. * @param id 索引ID
  60. * @return
  61. */
  62. public static boolean deleteById(String id) {
  63. try {
  64. client.deleteById(id);
  65. UpdateResponse resp = client.commit();
  66. if (resp.getStatus() == 0) {
  67. log.debug("delete successfully!");
  68. return true;
  69. }
  70. } catch (Exception e) {
  71. log.error(e.getMessage());
  72. e.printStackTrace();
  73. }
  74. log.debug("delete failure!");
  75. return false;
  76. }
  77. /**
  78. * 通过查询删除Solr中对应的数据集合
  79. *
  80. * @param query 查询条件
  81. */
  82. public static boolean deleteByQuery(String query) {
  83. try {
  84. client.deleteByQuery(query);
  85. UpdateResponse resp = client.commit();
  86. if (resp.getStatus() == 0) {
  87. log.debug("delete successfully!");
  88. return true;
  89. }
  90. } catch (Exception e) {
  91. log.error(e.getMessage());
  92. e.printStackTrace();
  93. }
  94. log.debug("delete failure!");
  95. return false;
  96. }
  97. /**
  98. * 更新Solr中的文档,Map对象中必须存在id用于定位doc文档
  99. *
  100. * @param map Key<String>代表数据域名称,Value<Object>代表修改值
  101. * @return
  102. */
  103. public static boolean update(Map<String, Object> map) {
  104. try {
  105. String id = (String) map.get("id");
  106. SolrInputDocument doc = new SolrInputDocument();
  107. doc.addField("id", id);
  108. for (String key : map.keySet()) {
  109. // 数据域Id忽略更新
  110. if (!"id".equals(key)) {
  111. Map fieldMap = new HashMap();
  112. fieldMap.put("set", map.get(key));
  113. doc.addField(key, fieldMap);
  114. }
  115. }
  116. client.add(doc);
  117. UpdateResponse resp = client.commit();
  118. if (resp.getStatus() == 0) {
  119. log.debug("update successfully!");
  120. return true;
  121. }
  122. } catch (Exception e) {
  123. log.error(e.getMessage());
  124. e.printStackTrace();
  125. }
  126. log.debug("update failure!");
  127. return false;
  128. }
  129. /**
  130. * 批量新增或更新记录
  131. *
  132. * @param entities 新增或更新对象列表
  133. * @param <T> 泛型
  134. * @return
  135. * @throws SolrServerException
  136. * @throws IOException
  137. */
  138. public static <T> boolean batchSaveOrUpdate(List<T> entities) throws SolrServerException, IOException {
  139. DocumentObjectBinder binder = new DocumentObjectBinder();
  140. int total = entities.size();
  141. int count = 0;
  142. for (T t : entities) {
  143. SolrInputDocument doc = binder.toSolrInputDocument(t);
  144. client.add(doc);
  145. log.debug("添加数据到索引中,总共要添加 %d 条记录,当前添加第%d条 %n", total, ++count);
  146. }
  147. client.commit();
  148. log.debug("batch Save Or Update successfully!");
  149. return true;
  150. }
  151. /**
  152. * 通过泛型获取Solr中的对象集合
  153. *
  154. * @param clz 泛型类对应java.lang.Class
  155. * @param query 数据域名称:数据域的值;查询全部*:*;多条件查询 name:Java AND age:20
  156. * @param hlFieldsList 高亮显示数据域名称,是List<String>集合
  157. * @param page 第几页
  158. * @param rows 每页显示记录数
  159. * @return
  160. */
  161. public static <T> SolrResultInfo<T> query(Class<T> clz, String query, List<String> hlFieldsList, Integer page, Integer rows) {
  162. try {
  163. // 定义返回自定义数据结构对象
  164. SolrResultInfo<T> resultInfo = new SolrResultInfo<T>();
  165. SolrQuery q = new SolrQuery();
  166. // 查询条件
  167. q.set("q", query);
  168. // 过滤条件
  169. q.set("fl", "*");
  170. // 高亮设置(开启)
  171. q.setHighlight(true);
  172. // 高亮显示字段
  173. String hlField = "";
  174. for (String s : hlFieldsList) {
  175. hlField = hlField + s + ",";
  176. }
  177. if (hlField.endsWith(",")) {
  178. hlField = hlField.substring(0, hlField.length() - 1);
  179. }
  180. q.set("hl.fl", hlField);
  181. // 高亮样式
  182. q.setHighlightSimplePre("<font color=\"red\">");
  183. q.setHighlightSimplePost("</font>");
  184. // 分页设置
  185. q.setStart((page - 1) * rows);
  186. q.setRows(rows);
  187. // 查询响应对象
  188. QueryResponse qr = client.query(q);
  189. Map<String, Map<String, List<String>>> hlMap = qr.getHighlighting();
  190. log.debug(hlMap.toString());
  191. // 高亮结果处理
  192. SolrDocumentList lst = qr.getResults();
  193. List<T> rtn = new ArrayList<T>();
  194. Long total = qr.getResults().getNumFound();
  195. for (SolrDocument doc : lst) {
  196. String id = (String) doc.getFieldValue("id");
  197. T t = clz.newInstance();
  198. // 获取自定义类所有属性名称
  199. Field[] fields = getField(clz);
  200. for (Field field : fields) {
  201. String fieldName = field.getName();
  202. String solrFldName = getSolrFieldName(clz, field);
  203. String fObj = getSingleValue(doc.getFieldValue(solrFldName));
  204. if (fObj == null) {
  205. continue;
  206. }
  207. if (field.getType() == java.sql.Date.class) {
  208. java.util.Date dt = new java.util.Date(fObj);
  209. fObj = new java.sql.Date(dt.getTime()).toString();
  210. }
  211. if (field.getType() == java.sql.Timestamp.class) {
  212. java.util.Date dt = new java.util.Date(fObj);
  213. fObj = new java.sql.Timestamp(dt.getTime()).toString();
  214. }
  215. if (field.getType() == java.sql.Time.class) {
  216. java.util.Date dt = new java.util.Date(fObj);
  217. fObj = new java.sql.Time(dt.getTime()).toString();
  218. }
  219. // 高亮显示数据形式:Map<ID, Map<FieldName,[MultiValue]>>
  220. if (hlFieldsList.contains(fieldName)) {
  221. //Map<FieldName,List<MultiValue>>
  222. Map<String, List<String>> fldMap = hlMap.get(id);
  223. Object hlObj = fldMap.get(fieldName);
  224. String hlVal = getSingleValue(hlObj);
  225. if (hlVal != null)
  226. fObj = hlVal;
  227. }
  228. if (fObj != null) {
  229. BeanUtils.setProperty(t, fieldName, fObj);
  230. }
  231. }
  232. rtn.add(t);
  233. }
  234. resultInfo.setList(rtn);
  235. resultInfo.setTotal(total);
  236. return resultInfo;
  237. } catch (Exception e) {
  238. log.error(e.getMessage());
  239. e.printStackTrace();
  240. }
  241. return null;
  242. }
  243. /**
  244. * 根据Class对象获取此类型的定义属性数据
  245. *
  246. * @param clz class对象
  247. * @return
  248. */
  249. private static Field[] getField(Class clz) {
  250. return clz.getDeclaredFields();
  251. }
  252. /**
  253. * 通过Field对象取得其上定义的注解名称
  254. *
  255. * @param clz
  256. * @param fld
  257. * @return
  258. */
  259. private static String getSolrFieldName(Class clz, Field fld) {
  260. org.apache.solr.client.solrj.beans.Field fld2 = fld.getAnnotation(org.apache.solr.client.solrj.beans.Field.class);
  261. if (fld2 == null) {
  262. return fld.getName();
  263. }
  264. if (fld2.value().equals("#default")) {
  265. return fld.getName();
  266. } else {
  267. return fld2.value();
  268. }
  269. }
  270. /**
  271. * 转化多值域为单值
  272. *
  273. * @param obj
  274. * @return
  275. */
  276. private static String getSingleValue(Object obj) {
  277. if (obj == null) {
  278. return null;
  279. }
  280. String val = obj.toString();
  281. if (val.startsWith("[") && val.endsWith("]")) {
  282. return val.substring(1, val.length() - 1);
  283. }
  284. return val;
  285. }
  286. /**
  287. * @author polaris <450733605@qq.com>
  288. * Description 查询Solr返回的对象,对象类型为T的集合,还包含Solr中符合条件记录总数
  289. * Date 2020-8-20 9:54
  290. * Version 1.0.0
  291. */
  292. static class SolrResultInfo<T> {
  293. private List<T> list = null;
  294. private Long total = null;
  295. public List<T> getList() {
  296. return list;
  297. }
  298. public void setList(List<T> list) {
  299. this.list = list;
  300. }
  301. public Long getTotal() {
  302. return total;
  303. }
  304. public void setTotal(Long total) {
  305. this.total = total;
  306. }
  307. }
  308. }

■ 测试类(SolrUtilTests.java)

  1. import com.lonton.bigdata.pojo.Article;
  2. import org.apache.solr.client.solrj.SolrServerException;
  3. import org.junit.*;
  4. import java.io.IOException;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;
  9. /**
  10. * Description 单元测试(Solr工具类)
  11. */
  12. public class SolrUtilTests {
  13. /**
  14. * BeforeClass:会在所有方法被调用前被执行,
  15. * 而且该方法是静态的,所有当测试类被加载后接着就会运行它,
  16. * 而且在内存中它只会存在一份实例,它比较适合加载配置文件
  17. **/
  18. @BeforeClass
  19. public static void setUpBeforeClass() {
  20. System.out.println("this is @BeforeClass ...");
  21. }
  22. /**
  23. * AfterClass:通常用来对资源的清理,如关闭数据库的连接
  24. **/
  25. @AfterClass
  26. public static void tearDownAfterClass() {
  27. System.out.println("this is @AfterClass ...");
  28. }
  29. /**
  30. * Before:每个测试方法调用前执行一次
  31. **/
  32. @Before
  33. public void setUp() {
  34. System.out.println("this is @Before ...");
  35. }
  36. /**
  37. * Before:每个测试方法调用后执行一次
  38. **/
  39. @After
  40. public void tearDown() {
  41. System.out.println("this is @After ...");
  42. }
  43. @Test
  44. public void addRecordByMap() {
  45. Map<String, Object> map = new HashMap<>();
  46. map.put("id", "105");
  47. map.put("content_id", 101L);
  48. map.put("title", "test我是中国人,打到小日本");
  49. map.put("content", "test作为一个中国人,我感到很自豪。");
  50. map.put("type", 1);
  51. map.put("create_at", 1578912614123L);
  52. map.put("publish_at", 1578912614125L);
  53. assert SolrUtil.add(map);
  54. }
  55. @Test
  56. public void deleteById() {
  57. addRecordByMap();
  58. assert SolrUtil.deleteById("105");
  59. }
  60. @Test
  61. public void deleteByQuery() {
  62. addRecordByMap();
  63. assert SolrUtil.deleteByQuery("id:105");
  64. }
  65. @Test
  66. public void deleteAll() {
  67. assert SolrUtil.deleteByQuery("*:*");
  68. }
  69. @Test
  70. public void update() {
  71. addRecordByMap();
  72. Map<String, Object> map = new HashMap<>();
  73. map.put("id", "105");
  74. map.put("content_id", 999L);
  75. map.put("title", "update-test");
  76. map.put("content", "update-test");
  77. map.put("type", 1);
  78. map.put("create_at", 1578912614199L);
  79. map.put("publish_at", 1578912614199L);
  80. assert SolrUtil.update(map);
  81. }
  82. @Test
  83. public void batchSaveOrUpdate() throws IOException, SolrServerException {
  84. List<Article> entities = new ArrayList<>();
  85. for (int i = 105; i <= 135; i++) {
  86. entities.add(new Article(i, i * 10L, "我是中国人,打倒小日本" + i, "作为一个中国人,我感到很自豪。", 1, 1578912614123L, 1578912614123L));
  87. }
  88. assert SolrUtil.batchSaveOrUpdate(entities);
  89. }
  90. @Test
  91. public void query() throws IOException, SolrServerException {
  92. batchSaveOrUpdate();
  93. List<String> hlFieldsList = new ArrayList<>();
  94. hlFieldsList.add("title");
  95. hlFieldsList.add("content");
  96. int page = 1;
  97. int rows = 5;
  98. SolrUtil.SolrResultInfo<Article> resultInfo = SolrUtil.query(Article.class, "keywords:中国", hlFieldsList, page, rows);
  99. Long total = resultInfo.getTotal();
  100. System.out.println("total:" + total);
  101. if (total > 0) {
  102. for (Article article : resultInfo.getList()) {
  103. System.out.println(article);
  104. }
  105. }
  106. }
  107. }

附件

完整案例代码:

参考

博客园:Solr7.4.0的API(Solrj)操作
https://www.cnblogs.com/frankdeng/p/9615856.html
CSDN:Solr操作工具类
https://blog.csdn.net/qixiang_chen/article/details/83076963