solr服务端安装
1、下载solr-8.0.0.zip版本:下载地址:http://archive.apache.org/dist/lucene/solr/,下载完后解压到相应目录下。
2、启动、关闭solr
在解压之后的solr目录中找到bin文件夹,进去之后右键进入Powershell输入以下命令:
启动 .\solr start
关闭 .\solr stop -all
3、创建core
在solr目录中的server\solr文件夹中创建一个core文件夹,然后把server\solr\configsets\sample_techproducts_configs下面的conf文件夹复制到刚才创建的core文件夹下面。
完成上面操作之后启动solr,启动成功之后打开浏览器进入http://localhost:8983/solr/#/地址,就可以看到solr的管理页面,点击左侧的Core Admin,在新页面的name和instanceDir输入框中分别修改为刚才创建的core文件夹名称,然后点击下面Add Core按钮即可成功创建core,创建成功之后,会在你刚才创建的core文件夹下面生成一个文件夹和一个文件,这样即表示创建成功。
删除solr数据
1)documents type 选择 XML
2)documents 输入下面语句
<delete><query>*:*</query></delete>
<commit/>
solr批量更新
solr支持三种类型的原子更新:
- set - to set a field.
- add - to add to a multi-valued field.
- inc - to increment a field.
其中set可以是单值的也可以是multifiled, add 针对multi-field ,inc 对应数值类型
关于更新中传入的_version_值说明:
- version<0,如果这个文档存在,则solr会拒绝修改,如果不存在,则add这个文档
- version=0时,如果待修改的文档存在,则修改这个文档,如果不存在。则add这个文档
- version=1 ,如果文档存在,则update这个文档,如果不存在,则拒绝修改
- version>1, 如果文档的_version_值和传入的version值不一样,则拒绝修改,值一样则修改。
原子更新的几点问题:
如果有字段的store=false,但是在更新的时候没有给这个字段设置值,则这个字段在更新的时候数据会被丢掉; store=true的字段则不会。
针对multi-field字段,如果store=false, 则在原子更新 使用add时也会把这个字段之前的数据丢掉。
批量更新思路:
定时任务处理,每次查询5000条数据,分10个线程跑,一个线程处理500条数据。
private void updateSolrAttachmentName() {
//查询共需处理多少条数据
int buseinssQueryCount = (int) buseinssQueryService.count();
//每次查询5000条数据
int toIndex = 5000;
for(int i=0;i<buseinssQueryCount;i+=toIndex){
if(i+toIndex>buseinssQueryCount){
toIndex = buseinssQueryCount-i;
}
List<BuseinssQueryEntity> buseinssQueryList = buseinssQueryService.findAllByPage(i,i+toIndex);
updateAttachmentName(buseinssQueryList);
}
}
多线程批量处理数据推送到solr
private void updateAttachmentName(List<BuseinssQueryEntity> list) {
// 开始时间
long start = System.currentTimeMillis();
// 每500条数据开启一条线程
int threadSize = 500;
// 总数据条数
int dataSize = list.size();
// 线程数
int threadNum = dataSize / threadSize + 1;
// 定义标记,过滤threadNum为整数
boolean special = dataSize % threadSize == 0;
// 创建一个线程池
ExecutorService exec = Executors.newFixedThreadPool(threadNum);
// 定义一个任务集合
List<Callable<List<BuseinssQueryEntity>>> tasks = new ArrayList<Callable<List<BuseinssQueryEntity>>>();
Callable<List<BuseinssQueryEntity>> task = null;
List<BuseinssQueryEntity> cutList = null;
// 确定每条线程的数据
for (int i = 0; i < threadNum; i++) {
if (i == threadNum - 1) {
if (special) {
break;
}
cutList = list.subList(threadSize * i, dataSize);
} else {
cutList = list.subList(threadSize * i, threadSize * (i + 1));
}
final List<BuseinssQueryEntity> listStr = cutList;
task = new Callable<List<BuseinssQueryEntity>>() {
@Override
public List<BuseinssQueryEntity> call() throws Exception {
return listStr;
}
};
// 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
tasks.add(task);
}
List<Future<List<BuseinssQueryEntity>>> results;
int sum=0;
try {
results = exec.invokeAll(tasks);
for (Future<List<BuseinssQueryEntity>> future : results) {
String url = "http://solr.hd.com:8983/solr/OA_HISTORY";
HttpSolrClient solrClient = new HttpSolrClient.Builder().withBaseSolrUrl(url).build();
Collection<SolrInputDocument> updateDocList = new ArrayList<>();
for (BuseinssQueryEntity buseinssQueryEntity : future.get()) {
try {
System.out.println("历史数据id:"+buseinssQueryEntity.getId());
//先查询附件名称是否有值
SolrQuery query = new SolrQuery();
query.set("fl", "attachmentName");
query.setFields("attachmentName");
query.set("q", "id:OCT_BUSINESSQUERY_"+buseinssQueryEntity.getId());
QueryResponse response = solrClient.query(query);
SolrDocumentList list1 = response.getResults();
System.out.println(list1.size());
if(list1==null||list1.size()==0) {
continue;
}
SolrDocument solrDoc = list1.get(0);
Map<String, Object> mapField = solrDoc.getFieldValueMap();
String attachmentNameStr = (String) mapField.get("attachmentName");
//如果附件名称没有值则进行更新
if(attachmentNameStr == null || attachmentNameStr == "") {
//根据附件关联uuid查询附件名称
StringBuffer buf = new StringBuffer("");
String attachmentName = "";
Attachment[] attachments = attachmentService.getAttachments(buseinssQueryEntity.getAttachment(), true);
String pdfName = buseinssQueryEntity.getPdfPath();
for(Attachment attachment:attachments){
if(pdfName.indexOf(attachment.getName())<0) {
buf.append(attachment.getName()).append(",");
}
}
int count = buf.toString().indexOf(",");
if(count>-1){
attachmentName =buf.substring(0, buf.length()-1);//去掉最后一个逗号
}
//附件有值才更新
if(attachmentName != null && attachmentName != "") {
SolrInputDocument document = new SolrInputDocument();
document.addField("id", "OCT_BUSINESSQUERY_"+buseinssQueryEntity.getId());
Map<String,String> map = new HashMap<String,String>();
map.put("add", attachmentName);
document.addField("attachmentName", map);
//version<0,如果这个文档存在,则solr会拒绝修改,如果不存在,则add这个文档
//version=0时,如果待修改的文档存在,则修改这个文档,如果不存在。则add这个文档
//version=1 ,如果文档存在,则update这个文档,如果不存在,则拒绝修改
//version>1, 如果文档的_version_值和传入的version值不一样,则拒绝修改,值一样则修改。
document.addField("_version_", 1);
updateDocList.add(document);
++sum;
}
}
} catch (Exception e) {
BuseinessQueryLogEntity buseinessQueryLog = new BuseinessQueryLogEntity();
buseinessQueryLog.setSrcId(buseinssQueryEntity.getSourceId());
buseinessQueryLog.setSrcTitle(buseinssQueryEntity.getTitle());
buseinessQueryLog.setError("定时任务同步附件名称异常");
String result;
String stackTrace = PigeonholeUtils.printStackTraceToString(e);
String exceptionType = e.toString();
String exceptionMessage = e.getMessage();
result = String.format("%s : %s \r\n %s", exceptionType, exceptionMessage, stackTrace);
buseinessQueryLog.setErrorStr(result);
buseinessQueryLog.setOperationTime(new DateTime());
buseinessQueryLog.setOperationAccount("hdadmin");
buseinessQueryLog.setTmpId(buseinssQueryEntity.getId().toString());
buseinessQueryLog.setSource(buseinssQueryEntity.getSystemType());
buseinessQueryLog.setDeleted(0);
buseinessQueryLogService.merge(buseinessQueryLog);
e.printStackTrace();
}
System.out.println(buseinssQueryEntity.getId()+",线程:"+Thread.currentThread().getName());//推送1000条花了9分钟
}
if(updateDocList.size()>0) {
solrClient.add(updateDocList);
solrClient.commit();
}
solrClient.close();
}
} catch (Exception e) {
e.printStackTrace();
}
// 关闭线程池
exec.shutdown();
System.out.println("共处理"+sum+"条数据");
System.err.println("执行任务消耗了 :" + (System.currentTimeMillis() - start) + "毫秒");
}
solr查询某个字段
public static void main(String[] args) {
try {
String url = "http://solr.hd.com:8983/solr/OA_HISTORY";
HttpSolrClient solrClient = new HttpSolrClient.Builder().withBaseSolrUrl(url).build();
SolrQuery query = new SolrQuery();
query.set("fl", "attachmentName");
query.setFields("attachmentName");
query.set("q", "id:OCT_BUSINESSQUERY_2501");
QueryResponse response = solrClient.query(query);
//转成对象集合
List<BuseinssQueryEntity> list = response.getBeans(BuseinssQueryEntity.class);
//转成SolrDocumentList
SolrDocumentList list1 = response.getResults();
SolrDocument document = list1.get(0);
Map<String, Object> map = document.getFieldValueMap();
String attachmentName = (String) map.get("attachmentName");
System.out.println(attachmentName);
} catch (Exception e) {
e.printStackTrace();
}
}