前面几节我们对 Solr 的运行有了个大概的了解,本文将介绍如何通过操作 API 来实现前面 web 控制台演示的那些功能的。

创建 Java 项目

使用 eclipse 新建一个 Java 项目,导入 apache-tomcat-7.0.42\webapps\solr\WEB-INF\lib 下面所有的 jar 包,再添加一个 junit4.8.1 的 jar 包

Solr 工程导入的 jar 包

新建一个测试类

废话不多说,直接上代码,API 操作还是比较简单的,就不分开说了。

SolrTest.java

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.FacetField.Count;
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.junit.After;
import org.junit.Before;
import org.junit.Test;

public class SolrTest {

	private static String url = "http://localhost:8080/solr/test";
	private SolrClient client;

	@Before
	public void init() {
		client = new HttpSolrClient(url);
	}

	@After
	public void destroy() {
		client = null;
	}

	// 单文档插入
	public void addDoc() throws Exception {
		SolrInputDocument doc = new SolrInputDocument();
		doc.addField("id", 10000001);
		doc.addField("name", "Solr Input Document");
		doc.addField("manu", "this is SolrInputDocument content");

		client.add(doc);
		client.commit();
	}

	// 批量文档插入
	public void addDocList() throws Exception {
		Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
		for (int i = 1; i < 11; i++) {
			SolrInputDocument doc = new SolrInputDocument();
			doc.addField("id", 1000000 + i);
			doc.addField("name", "batch solr document insert " + i);
			doc.addField("manu", "batch solr document content insert " + i);
			docs.add(doc);
		}

		client.add(docs);
		client.commit();
	}

	@Test
	// 单个文档对应的 Java Bean 插入
	public void addDocBean() throws Exception {
		Index doc = new Index();
		doc.setId("100000000");
		doc.setName("add bean document");
		doc.setManu("index bean manu 中文测试");
		doc.setCat(new String[] { "a1", "b2" });

		client.addBean(doc);
		client.commit();
	}

	// 批量文档 Bean 插入
	public void addDocBeanList() throws Exception {
		Collection<Index> docs = new ArrayList<Index>();
		for (int i = 1; i < 11; i++) {
			Index doc = new Index();
			doc.setId("10000000" + i);
			doc.setName("add bean document " + i);
			doc.setManu("bean document manu " + i);
			docs.add(doc);
		}

		client.addBeans(docs);
		client.commit();
	}

	// 根据 id 删除单个文档
	public void remove() throws Exception {
		client.deleteById("100000000");
		client.commit();
	}

	// 根据批量 id 删除文档
	public void removeList() throws Exception {
		List<String> ids = new ArrayList<String>();
		for (int i = 1; i < 6; i++) {
			ids.add("10000000" + i);
		}

		client.deleteById(ids);
		client.commit();
	}

	// 根据查询条件删除文档
	public void removeByQuery() throws Exception {
		client.deleteByQuery("id:100000007");
		client.commit();
	}

	// 查询操作
	public void queryAll() throws Exception {
		SolrQuery query = new SolrQuery();
		query.set("q", "*:*");
		query.setStart(0);
		query.setRows(Integer.MAX_VALUE);
		// query.set("start", 0);
		// query.set("row", Integer.MAX_VALUE);
		query.set("id", "id desc");
		query.set("fl", "*, score");

		QueryResponse response = client.query(query);

		SolrDocumentList docs = response.getResults();

		for (SolrDocument doc : docs) {
			log(doc);
		}
	}

	// 一些附属操作
	public void otherMethod() throws Exception {
		client.getBinder();
		client.optimize(); // 合并索引文件,可以优化索引、提供性能,但需要一定的时间
		client.ping(); // ping服务器是否连接成功
		client.rollback();
		client.commit();
	}

	// query 基本用法测试
	public void queryCase() {
		// AND 并且
		SolrQuery params = new SolrQuery("name:apple AND manu:inc");

		// OR 或者
		params.setQuery("name:apple OR manu:apache");
		// 空格 等同于 OR
		params.setQuery("name:server manu:dell");

		// params.setQuery("name:solr - manu:inc");
		// params.setQuery("name:server + manu:dell");

		// 查询name包含solr apple
		params.setQuery("name:solr,apple");
		// manu不包含inc
		params.setQuery("name:solr,apple NOT manu:inc");

		// 50 <= price <= 200
		params.setQuery("price:[50 TO 200]");
		params.setQuery("popularity:[5 TO 6]");

		// 50 <= price <= 200 AND 5 <= popularity <= 6
		params.setQuery("price:[50 TO 200] AND popularity:[5 TO 6]");
		params.setQuery("price:[50 TO 200] OR popularity:[5 TO 6]");

		// 过滤器查询,可以提高性能 filter 类似多个条件组合,如and
		// params.addFilterQuery("id:VA902B");
		// params.addFilterQuery("price:[50 TO 200]");
		// params.addFilterQuery("popularity:[* TO 5]");
		// params.addFilterQuery("weight:*");
		// 0 < popularity < 6 没有等于
		// params.addFilterQuery("popularity:{0 TO 6}");

		// 排序
		params.addSort("id", ORDER.asc);

		// 分页:start开始页,rows每页显示记录条数
		// params.add("start", "0");
		// params.add("rows", "200");
		// params.setStart(0);
		// params.setRows(200);

		// 设置高亮
		params.setHighlight(true); // 开启高亮组件
		params.addHighlightField("name");// 高亮字段
		params.setHighlightSimplePre("<font color='red'>");// 标记,高亮关键字前缀
		params.setHighlightSimplePost("</font>");// 后缀
		params.setHighlightSnippets(1);// 结果分片数,默认为1
		params.setHighlightFragsize(1000);// 每个分片的最大长度,默认为100

		// 分片信息
		params.setFacet(true).setFacetMinCount(1).setFacetLimit(5)// 段
				.addFacetField("name")// 分片字段
				.addFacetField("inStock");

		// params.setQueryType("");

		try {
			QueryResponse response = client.query(params);

			/*
			 * List<Index> indexs = response.getBeans(Index.class); for (int i =
			 * 0; i < indexs.size(); i++) { fail(indexs.get(i)); }
			 */

			// 输出查询结果集
			SolrDocumentList list = response.getResults();
			log("query result nums: " + list.getNumFound());
			for (int i = 0; i < list.size(); i++) {
				log(list.get(i));
			}

			// 输出分片信息
			List<FacetField> facets = response.getFacetFields();
			for (FacetField facet : facets) {
				log(facet);
				List<Count> facetCounts = facet.getValues();
				for (FacetField.Count count : facetCounts) {
					System.out.println(count.getName() + ": "
							+ count.getCount());
				}
			}
		} catch (SolrServerException e) {
			e.printStackTrace();
		}
	}

	// 分片查询, 可以统计关键字及出现的次数、或是做自动补全提示
	public void facetQueryCase() {
		SolrQuery params = new SolrQuery("*:*");

		// 排序
		params.addSort("id", ORDER.asc);

		params.setStart(0);
		params.setRows(200);

		// Facet为solr中的层次分类查询
		// 分片信息
		params.setFacet(true).setQuery("*:*").setFacetMinCount(1)
				.setFacetLimit(5)	// 段
				// .setFacetPrefix("electronics", "cat")
				.setFacetPrefix("cor")	// 查询manu、name中关键字前缀是cor的
				.addFacetField("manu").addFacetField("name");	// 分片字段

		try {
			QueryResponse response = client.query(params);

			// 输出查询结果集
			SolrDocumentList list = response.getResults();
			log("Query result nums: " + list.getNumFound());

			for (int i = 0; i < list.size(); i++) {
				log(list.get(i));
			}

			log("All facet filed result: ");
			// 输出分片信息
			List<FacetField> facets = response.getFacetFields();
			for (FacetField facet : facets) {
				log(facet);
				List<Count> facetCounts = facet.getValues();
				for (FacetField.Count count : facetCounts) {
					// 关键字 - 出现次数
					log(count.getName() + ": " + count.getCount());
				}
			}

			log("Search facet [name] filed result: ");
			// 输出分片信息
			FacetField facetField = response.getFacetField("name");
			List<Count> facetFields = facetField.getValues();
			for (Count count : facetFields) {
				// 关键字 - 出现次数
				log(count.getName() + ": " + count.getCount());
			}
		} catch (SolrServerException e) {
			e.printStackTrace();
		}
	}

	private void log(Object obj) {
		System.out.println(obj);
	}
}

里面用到一个 java bean Index.java,代码如下:

import org.apache.solr.client.solrj.beans.Field;

public class Index {  
    @Field  
    private String id;  
    @Field
    private String name;  
    @Field  
    private String manu;  
    @Field  
    private String[] cat;  
    @Field  
    private String[] features;  
    @Field  
    private float price;  
    @Field  
    private int popularity;  
    @Field  
    private boolean inStock;  
      
    public String getId() {  
        return id;  
    }  
      
    @Field  
    public void setId(String id) {  
        this.id = id;  
    }  
   
    public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getManu() {
		return manu;
	}

	public void setManu(String manu) {
		this.manu = manu;
	}

	public String[] getCat() {
		return cat;
	}

	public void setCat(String[] cat) {
		this.cat = cat;
	}

	public String[] getFeatures() {
		return features;
	}

	public void setFeatures(String[] features) {
		this.features = features;
	}

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}

	public int getPopularity() {
		return popularity;
	}

	public void setPopularity(int popularity) {
		this.popularity = popularity;
	}

	public boolean isInStock() {
		return inStock;
	}

	public void setInStock(boolean inStock) {
		this.inStock = inStock;
	}

	public String toString() {  
        return this.id + "#" + this.name + "#" + this.manu + "#" + this.cat;  
    }  
}