实例
在构建索引库后需要对schema.xml配置文件中添加需要搜索的字段名。
schema.xml配置
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<!-- docValues are enabled by default for long type so we don't need to index the version field -->
<field name="_version_" type="plong" indexed="false" stored="false"/>
<field name="_root_" type="string" indexed="true" stored="false" docValues="false" />
<field name="_text_" type="text_general" indexed="true" stored="false" multiValued="true"/>
<!--name、phoneType、price字段对应保存的字段名-->
<field name="name" type="string" indexed="true" stored="true"/>
<field name="phoneType" type="string" indexed="true" stored="true"/>
<field name="price" type="string" indexed="true" stored="true"/>
通过SolrJ客户端连接Solr
1、创建实体类Phone
package solrtest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.apache.solr.client.solrj.beans.Field;
import org.apache.solr.common.SolrInputDocument;
public class Phone {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Field("id")
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhoneType() {
return phoneType;
}
public void setPhoneType(String phoneType) {
this.phoneType = phoneType;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
@Field(value = "name")
private String name;
@Field(value = "phoneType")
private String phoneType;
@Field(value = "price")
private String price;
}
2、对Solr中的数据进行增删改查
package solrtest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
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 net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class SolrService {
private static final String SOLR_PATH = "http://192.168.121.12:8080/solr/core";
// 实例化solr对象
private static final HttpSolrClient solrServer = new HttpSolrClient.Builder(SOLR_PATH).
withConnectionTimeout(100000).withSocketTimeout(1000).build();
public static void addIndex(Phone phone) throws Exception, IOException {
// 创建一个文档
//添加的Field 必须是在schema.xml 中配置了,不然就报错
// 创建文档2
solrServer.addBean(phone);
// 提交
solrServer.commit();
}
public static void addIndex(JSONObject jsonObject) throws Exception, IOException {
// 创建一个文档
SolrInputDocument doc = new SolrInputDocument();
doc.addField("name", jsonObject.getString("name"));
doc.addField("id", UUID.randomUUID().toString());
doc.addField("phoneType", jsonObject.getString("phoneType"));
doc.addField("price", jsonObject.getString("price"));
solrServer.add(doc);
// 提交
solrServer.commit();
}
public static void addIndexs(JSONArray jsonArray) throws Exception, IOException {
List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
for(int i=0;i<jsonArray.size();i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
SolrInputDocument doc = new SolrInputDocument();
doc.addField("name", jsonObject.getString("name"));
doc.addField("id", UUID.randomUUID().toString());
doc.addField("phoneType", jsonObject.getString("phoneType"));
doc.addField("price", jsonObject.getString("price"));
docs.add(doc);
}
solrServer.add(docs);
// 提交
solrServer.commit();
}
public static void addIndexs(List<Phone> phoneList) throws Exception, IOException {
solrServer.addBeans(phoneList);
solrServer.commit();
}
//通过指定的id删除数据
public void delete(List<String> ids) throws Exception {
this.solrServer.deleteById(ids);
this.solrServer.commit(); //提交
}
//通过指定的域值删除数据
public void deleteByField(String fieldName,String fieldValue) throws Exception {
String query = fieldName + ":" + fieldValue;
this.solrServer.deleteByQuery(query);
this.solrServer.commit(); //提交
}
//通过指定的域值更新数据
public void updateByField(String id,String fieldName,String fieldValue) throws Exception {
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", id);
doc.addField(fieldName, fieldValue);
this.solrServer.add(doc);
this.solrServer.commit(); //提交
}
//查询索引
public static void query(String fieldName,String fieldValue, Integer page, Integer rows,String fieldSort) throws Exception {
//添加查询
SolrQuery solrQuery = new SolrQuery();
//查询
//代表Solr控制界面Query中的p字段 ,查询字符串,这个是必须的。
//如果查询所有*:* ,根据指定字段查询(Name:张三 AND Address:北京)
//solrQuery.set(fieldName, fieldValue);
solrQuery.setQuery(fieldName+":"+fieldValue);
//代表fq字段 ,(filter query)过虑查询,作用:在q查询符合结果中同时是fq查询符合的,
//例如:q=Name:张三&fq=CreateDate:[20081001 TO 20091031],找关键字mm,并且CreateDate是20081001
// solrQuery.addFilterQuery("itemName:yby");
//指定返回那些字段内容,用逗号或空格分隔多个。
solrQuery.addField("id,phoneType,price");
//按照指定的字段排序
solrQuery.setSort(fieldSort, ORDER.asc);
// 设置分页 start=0就是从0开始,,rows=5当前返回5条记录,第二页就是变化start这个值为5就可以了。
solrQuery.setStart((Math.max(page, 1) - 1) * rows);
solrQuery.setRows(rows);
// 设置高亮
solrQuery.setHighlight(true); // 开启高亮组件
solrQuery.addHighlightField("id");// 高亮字段
solrQuery.setHighlightSimplePre("<em>");// 标记,高亮关键字前缀
solrQuery.setHighlightSimplePost("</em>");// 后缀
//获取查询结果
QueryResponse response = solrServer.query(solrQuery);
//获取查询到的文档
SolrDocumentList docs = response.getResults();
//查询到的条数
long cnt = docs.getNumFound();
System.out.println("查询到的条数\t"+cnt);
//获取查询结果
for(SolrDocument doc :docs) {
String id = doc.get("id").toString();
System.out.printf("%s\r\n",id);
String phoneType = doc.get("phoneType").toString();
System.out.printf("%s\r\n",phoneType);
}
}
}
客户端详解
1、solrJ客户端实例创建并设置连接超时时间
final String solrUrl = "http://127.0.0.1:8080/solr";
//创建solrClient同时指定超时时间,不指定走默认配置
HttpSolrClient build = new HttpSolrClient.Builder(solrUrl)
.withConnectionTimeout(10000)
.withSocketTimeout(60000)
.build();
不同solr版本solrj 的创建方式有所不同
//solr4创建方式
//SolrServer solrServer = new HttpSolrServer("http://127.0.0.1:8080/solr");
//solr5创建方式,在url中指定core名称:core1
//HttpSolrClient solrServer=new HttpSolrClient("http://127.0.0.1:8080/solr/core1");
//solr7创建方式,在url中指定core名称:core1
HttpSolrClient solrServer= new HttpSolrClient.Builder("http://127.0.0.1:8080/solr/core1").build();
2、Java对象绑定
SolrJ提供两个有用的接口,UpdateResponse
和 QueryResponse,它们可以很方便的处理特定域的对象,可以使您的应用程序更容易被理解。SolrJ支持通过
每个实例变量在Java对象可以映射到一个相应的Solr字段中,使用 @Field注解
隐式转换文档与任何类。field注解
。
managed-schema文件配置
<!--配置ik分词器-->
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
<analyzer type="query" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
<!--配置ik分词器-->
<field name="name_ik" type="text_ik" indexed="true" stored="true"/>
<!--项目中的字段-->
<field name="p_name" type="text_ik" indexed="true" stored="true"/>
<field name="p_catalog_name" type="string" indexed="true" stored="true"/>
<field name="p_price" type="pfloat" indexed="true" stored="true"/>
<field name="p_number" type="plong" indexed="true" stored="true"/>
<field name="p_description" type="text_ik" indexed="true" stored="true"/>
<field name="p_picture" type="string" indexed="false" stored="true"/>
<!--关键词 定义复制域字段,将商品名称和商品描述都复制到 product_keywords这一个字段上-->
<field name="p_keywords" type="text_ik" indexed="true" stored="false" multiValued="true" />
<copyField source="p_name" dest="p_keywords" />
<copyField source="p_description" dest="p_keywords" />
其中 indexed="true" 表示开启索引(当字段不需要被检索时,最好不要开启索引,) stored="true"表示存储原来数据(当字段不被检索,而只是需要通过其他字段检索而获得时,要设为true) multiValued="true" 表示返回多值,如一个返回多个content,此时要在java代码中把 content设置 集合或数组类型。
首先需要创建对象Product,字段必须与schema.xml或managed-schema配置文件的field的一致,该配置文件中必需有这个field,不然会报错。
①字段写错:查询时不报错,查不出来想要的数据,添加时创建的索引字段也不是自己想要的field。
②字段type类型不一致:Caused by: java.long.IllegalArgementException:Can not set java.lang.Integer field junit.Product.id to java.long.String。