solr总结
Posted cuihongyu3503319
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了solr总结相关的知识,希望对你有一定的参考价值。
Solr的使用:
在Tomcat中部署solr
查
http://www.cnblogs.com/chen108/p/6218234.html
1、solr的data-config配置文件:
<dataConfig>
<dataSource name="jdbc" driver="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@//192.168.82.192:1521/orcl" user="zykapp" password="zykapp"/>
<document >
<entity name="item" pk="SID" query="select * from adba_res_awimg" dataSource="ds-1" transformer="ClobTransformer,DateFormatTransformer">
<field name="sid" column="SID" />
<entity name="resTypeName" query="select ‘艺术品图片‘ as resTypeName from dual" transformer="ClobTransformer"/>
<field name="code" column="CODE" />
<field name="titleName" column="TITLE_NAME" />
<field name="awCode" column="AW_CODE" />
<field name="titleOther" column="TITLE_OTHER" />
<field name="titleCreationDt" column="TITLE_CREATION_DT" />
<field name="picAuthor" column="PIC_AUTHOR" clob="true" />
<field name="desCoiaq" column="DES_COIAQ" />
<field name="picAppendix" column="PIC_APPENDIX" />
<field name="desAiosas" column="DES_AIOSAS" />
<field name="desDimension" column="DES_DIMENSION" />
<field name="themeKw" column="THEME_KW" />
<field name="desBizSource" column="DES_BIZ_SOURCE" />
<field name="desSummary" column="DES_SUMMARY" clob="true" />
<field name="accessLevel" column="ACCESS_LEVEL" />
<field name="owner" column="OWNER" />
<field name="dataStatus" column="DATA_STATUS" />
<field name="dataPhase" column="DATA_PHASE" />
<field name="lang" column="LANG" />
<field name="isDefault" column="IS_DEFAULT" />
<field name="crStatus" column="CR_STATUS" />
<entity name="swDt" column="swDt" query="select a.sw_dt as swDt from adba_mgmt_res_sw a where a.res_code=‘${item.CODE}‘" transformer="ClobTransformer"/>
<entity name="catName" column="catName" query="select c.cnt_chi as catName from adba_res_cat c where c.sid in (select cat_sid from adba_res_ins_r2_cat ic where ic.res_code=‘${item.CODE}‘ and ic.res_type_sid=‘2‘)" transformer="ClobTransformer"/>JXH.JXH.01050214
<entity name="catCode" column="catCode" query="
select c.code as catCode from ADBA_RES_CAT c where c.type=1 and c.res_type_sid=2 and c.sid=(
select t.cat_sid from ADBA_RES_INS_R2_CAT t where t.res_code==‘${item.CODE}‘)" transformer="ClobTransformer"/>
<entity name="dcCode" column="dcCode" query="
select t.code as dcCode from ADBA_RES_DC t where t.type=1 and t.sid in (
select a.dc_sid from ADBA_RES_INS_R2_DC a where a.res_code=‘${item.CODE}‘ and a.res_type_sid=2)" transformer="ClobTransformer"/>
<entity name="aucCurrency" column="aucCurrency" query="
select t.auc_currency as aucCurrency from ADBA_RES_ACTIVITY_R2_AW t where t.res_code=‘${item.CODE}‘ and t.res_type_sid=2" transformer="ClobTransformer"/>
<entity name="aucTurnoverStatus" column="aucTurnoverStatus" query="
select t.AUC_TURNOVER_STATUS AS aucTurnoverStatus from ADBA_RES_ACTIVITY_R2_AW t where t.res_code=‘${item.CODE}‘ and t.res_type_sid=2" transformer="ClobTransformer"/>
<!--如果添加的字段。不是对象本身的字段,而是和其他表关联的出的字段,那么需要使用SQL语句查询,此事需要使用<entity>标签,其他的可以使用<field>标签,同时在data_config.xml中添加的字段,在schema.xml中也要添加相应的字段,否则添加不成功-->
</entity>
</document>
</dataConfig>
//这个配置文件只能怪的字段修改主要是为了,在solr界面手动的导入数据时,需要配置该位置的字段;如果使用java代码导入数据时,在不需要配置这个文件的字段,也可以把数据导入成功。
2.solr的schema.xml配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="example" version="1.5">
<fields>
<field name="_version_" type="long" indexed="true" stored="true"/>
<field name="_root_" type="string" indexed="true" stored="false"/>
<field name="qAllDefaultValue" type="string" indexed="true" stored="false"/>
<field name="sid" type="long" indexed="true" stored="true" required="true" />
<field name="resTypeName" type="text_chinese_JCSEG" indexed="true" stored="true" />
<field name="relationCode" type="text_word" indexed="true" stored="true" multiValued="true" />
<field name="catName" type="text_en_splitting_tight" indexed="true" stored="true" multiValued="false" />
<field name="catNameKey" type="text_chinese_JCSEG" indexed="true" stored="true" multiValued="false" />
<field name="relationCatName" type="text_word" indexed="true" stored="true" multiValued="false" />
<field name="relationCatNameKey" type="text_chinese_JCSEG" indexed="true" stored="true" multiValued="false" />
<field name="all" type="text_chinese_JCSEG" indexed="true" stored="false" multiValued="true" />
<dynamicField name="dcName*" type="text_word" indexed="true" stored="true" multiValued="true"/>
<dynamicField name="dcNameKey*" type="text_chinese_JCSEG" indexed="true" stored="true" multiValued="true"/>
<dynamicField name="relationDcName*" type="text_word" indexed="true" stored="true" multiValued="true"/>
<dynamicField name="relationDcNameKey*" type="text_chinese_JCSEG" indexed="true" stored="true" multiValued="true"/>
</fields>
<copyField source="qAllDefaultValue" dest="all"/>
<copyField source="resTypeName" dest="all"/>
<types>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<!-- boolean type: "true" or "false" -->
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
<fieldType name="text_chinese_JCSEG" class="solr.TextField">
<analyzer type="index">
<tokenizer class="org.lionsoul.jcseg.solr.JcsegTokenizerFactory" mode="complex"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.lionsoul.jcseg.solr.JcsegTokenizerFactory" mode="complex"/>
</analyzer>
</fieldType>
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
<analyzer type="query" >
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="text_word" class="solr.TextField" positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<!-- Case insensitive stop word removal.
-->
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords_en.txt"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
<filter class="solr.EnglishMinimalStemFilterFactory"/>
-->
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords_en.txt"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
<filter class="solr.EnglishMinimalStemFilterFactory"/>
-->
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="text_en_splitting" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<!-- Case insensitive stop word removal.
-->
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords_en.txt"
/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords_en.txt"
/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
<!-- Less flexible matching, but less false matches. Probably not ideal for product names,
but may be good for SKUs. Can insert dashes in the wrong place and still match. -->
<fieldType name="text_en_splitting_tight" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
<analyzer>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords_en.txt"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.EnglishMinimalStemFilterFactory"/>
<!-- this filter can remove any duplicate tokens that appear at the same position - sometimes
possible with WordDelimiterFilter in conjuncton with stemming. -->
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
</fieldType>
<!-- Just like text_general except it reverses the characters of
each token, to enable more efficient leading wildcard queries. -->
<fieldType name="text_general_rev" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.ReversedWildcardFilterFactory" withOriginal="true"
maxPosAsterisk="3" maxPosQuestion="2" maxFractionAsterisk="0.33"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
</types>
<!-- Similarity is the scoring routine for each document vs. a query.
A custom Similarity or SimilarityFactory may be specified here, but
the default is fine for most applications.
For more info: http://wiki.apache.org/solr/SchemaXml#Similarity
-->
<!--
<similarity class="com.example.solr.CustomSimilarityFactory">
<str name="paramkey">param value</str>
</similarity>
-->
</schema>
3.solr的solrConfig.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
This is a stripped down config file used for a simple example...
It is *not* a good example to work from.
-->
<config>
<luceneMatchVersion>4.7</luceneMatchVersion>
<!-- The DirectoryFactory to use for indexes.
solr.StandardDirectoryFactory, the default, is filesystem based.
solr.RAMDirectoryFactory is memory based, not persistent, and doesn‘t work with replication. -->
<directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/>
<dataDir>${solr.data.dir:}</dataDir>
<query>
<filterCache class="solr.FastLRUCache" size="512" initialSize="512" autowarmCount="0"/>
</query>
<!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>:
<schemaFactory class="ManagedIndexSchemaFactory">
<bool name="mutable">true</bool>
<str name="managedSchemaResourceName">managed-schema</str>
</schemaFactory>
When ManagedIndexSchemaFactory is specified, Solr will load the schema from
he resource named in ‘managedSchemaResourceName‘, rather than from schema.xml.
Note that the managed schema resource CANNOT be named schema.xml. If the managed
schema does not exist, Solr will create it after reading schema.xml, then rename
‘schema.xml‘ to ‘schema.xml.bak‘.
Do NOT hand edit the managed schema - external modifications will be ignored and
overwritten as a result of schema modification REST API calls.
When ManagedIndexSchemaFactory is specified with mutable = true, schema
modification REST API calls will be allowed; otherwise, error responses will be
sent back for these requests.
-->
<schemaFactory class="ClassicIndexSchemaFactory"/>
<updateHandler class="solr.DirectUpdateHandler2">
<updateLog>
<str name="dir">${solr.core0.data.dir:}</str>
</updateLog>
<autoCommit>
<maxTime>15000</maxTime>
<openSearcher>true</openSearcher>
</autoCommit>
<autoSoftCommit>
<maxTime>10000</maxTime>
</autoSoftCommit>
</updateHandler>
<!-- realtime get handler, guaranteed to return the latest stored fields
of any document, without the need to commit or open a new searcher. The current
implementation relies on the updateLog feature being enabled. -->
<requestHandler name="/get" class="solr.RealTimeGetHandler">
<lst name="defaults">
<str name="omitHeader">true</str>
</lst>
</requestHandler>
<requestHandler name="/replication" class="solr.ReplicationHandler">
<lst name="master">
<str name="replicateAfter">startup</str>
<str name="replicateAfter">commit</str>
<str name="commitReserveDuration">00:00:10</str>
<str name="confFiles">schema.xml,stopwords.txt,synonyms.txt</str>
</lst>
</requestHandler>
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
<!-- 显示data-config.xml存放的位置 -->
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
<requestDispatcher handleSelect="true" >
<requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="2048" formdataUploadLimitInKB="2048" />
</requestDispatcher>
<requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
<requestHandler name="/analysis/field" startup="lazy" class="solr.FieldAnalysisRequestHandler" />
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
<requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" />
<requestHandler name="/admin/ping" class="solr.PingRequestHandler">
<lst name="invariants">
<str name="q">solrpingquery</str>
</lst>
<lst name="defaults">
<str name="echoParams">all</str>
</lst>
</requestHandler>
<!-- config for the admin interface -->
<admin>
<defaultQuery>solr</defaultQuery>
</admin>
</config>
4.solr的java代码的编写:(对solr进行存)
package com.thinkgem.jeesite.modules.solr.web;
@Repository
public class CreatAwimgSolr{
Logger logger = Logger.getLogger(CreatAwimgSolr.class);
ExecutorService threadPool = Executors.newCachedThreadPool();
@Autowired
private AdbaResAwimgService adbaResAwimgService;
@Autowired
private AdbaResDcService adbaResDcService;
@Resource(name ="adbaResAwimgRepositoryImpl")
private AdbaResAwimgRepository adbaResAwimgRepository;
private int count;
private int pageSize=500;
public CreatAwimgSolr() {
super();
}
private IndexManage indexManage=new IndexManage();
private Long num=0L;
public boolean fromOracle(){
boolean b = false;
String maxId="0";
AdbaResAwimg adbaResAwimgCount = adbaResAwimgService.findCount(new AdbaResAwimg());
count = adbaResAwimgCount.getSidCount();
indexManage.setCount(count);
indexManage.setDoneCount(0);
logger.debug("start:" + new Date().getTime());
List<AdbaResAwimg > list =adbaResAwimgService.getAwimgs(pageSize, maxId);
while(list!=null && list.size()>0){
maxId=Collections.max(getListIds(list));
threadPool.execute(new AwimgSolrThread(list));
list=adbaResAwimgService.getAwimgs(pageSize,maxId);
}
b = true;
return b;
}
public List<String> getListIds(List<AdbaResAwimg > list){
List<String> ids = Lists.newArrayList();
for(AdbaResAwimg a:list){
if(StringUtils.isNotBlank(a.getSid())){
ids.add(a.getSid());
/* logger.debug(Thread.currentThread().getName() +"个数:"+num++);*/
}
}
return ids;
}
public void saveSolr(List<AdbaResAwimg> lists){
List<AdbaResAwimgCore> list = Lists.newArrayList();
if (adbaResAwimgRepository == null) {
logger.debug("数据为空");
indexManage.resetCount();
return;
}
int index = 0;
for(AdbaResAwimg awimgObj:lists){
if(StringUtils.isEmpty(awimgObj.getCode())){
logger.debug("该类不存在code方法,请重写该方法");
return;
}
String catCode = adbaResAwimgService.getCatCode(awimgObj.getCode());
List<String> dcCode = adbaResDcService.getdcCode(awimgObj.getCode());
Long aucCurrency = adbaResAwimgService.getAucCurrency(awimgObj.getCode());
Long aucTurnoverStatus=adbaResAwimgService.getAucTurnoverStatus(awimgObj.getCode());
AdbaResAwimgCore entityCore = new AdbaResAwimgCore();
entityCore.setCatCode(catCode);
entityCore.setDcCode(dcCode);
entityCore.setAucCurrency(aucCurrency);
entityCore.setAucTurnoverStatus(aucTurnoverStatus);
/*该部分为必须改变的内容,如果添加新的字段,则该部分也需要添加(entityCore.set字段名(字段))新的字段,并且把心得字段添加到对应的Core中,同时在core的 类中也要有该字段。*/
System.out.println(entityCore);
BeanUtils.copyProperties(awimgObj, entityCore);
list.add(entityCore);
if (++index == pageSize) {
createSolr4List(adbaResAwimgRepository,list,index);
index = 0;
}
}
if(list.size()>0)
createSolr4List(adbaResAwimgRepository,list,index);
indexManage.resetCount();
logger.debug(Thread.currentThread().getName() + "-------" + DateUtils.formatDateTime(new Date().getTime()));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void createSolr4List(SolrCrudRepository solrCrudRepository, List<?> saveList, int index) {
IndexManage manage=new IndexManage();
try {
System.out.println("// 创建索引");
if(solrCrudRepository instanceof SoftCommitRepository){
SoftCommitRepository aa=(SoftCommitRepository)solrCrudRepository;
aa.saveSoftCommit(saveList);
}else{
solrCrudRepository.save(saveList);
}
indexManage.setDoneCount(indexManage.getDoneCount() + pageSize);
if (indexManage.getDoneCount() > indexManage.getCount()) {
indexManage.setDoneCount(indexManage.getCount());
}
} catch (Exception e) {
manage.resetCount();
logger.debug("create solr index error:" + e.getMessage());
return;
} finally {
saveList.clear();
index = 0;
}
}
/**
* 实体转solrImputDocument
*
* @author [email protected] 实体类与 SolrInputDocument 转换
* @param obj
* 实体对象
* @return SolrInputDocument SolrInputDocument 对象
*/
public static SolrInputDocument entity2SolrInputDocument(Object obj) {
if (obj != null) {
Class<?> cls = obj.getClass();
Field[] filedArrays = cls.getDeclaredFields(); // 获取类中所有属性
Method getMethod = null;
SolrInputDocument sid = new SolrInputDocument();
for (Field f : filedArrays) { // 因为如果对象序列化之后 , 会增加该属性 , 不用对该属性进行反射
if (!f.getName().equals("serialVersionUID")) {
try {
// 跟进属性 xx 构造对应的 getXx() 方法
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), obj.getClass());
if (pd != null) {
getMethod = pd.getReadMethod();// 获得get方法
// 属性名 , 与对应的属性值 get 方法获取到的值
sid.addField("" + f.getName(), getMethod.invoke(obj));
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IntrospectionException e) {
e.printStackTrace();
}
}
}
return sid;
}
return null;
}
/**
* 指定基础数据中要查询的字段名称,根据名称查找数据
*/
public String getMethodValue(Object t, String coreName) {
return (String) method(t, "code");
}
@SuppressWarnings("rawtypes")
public static Object method(Object obj, String filed) {
Object o = null;
try {
Class clazz = obj.getClass();
PropertyDescriptor pd = new PropertyDescriptor(filed, clazz);
Method getMethod = pd.getReadMethod();// 获得get方法
if (pd != null) {
o = getMethod.invoke(obj);// 执行get方法返回一个Object
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return o;
}
public static String getCodeStart(String code){
String code_="";
if (StringUtils.isNotBlank(code)) {
char[] cha = code.toCharArray();
for (int i = 0; i < cha.length; i++) {
if((!Character.isDigit(cha[i]))&&i==cha.length-1){
code_ =code.substring(0, cha.length);
break;
}
if (Character.isDigit(cha[i])){//0~9 返回true,否则是false
code_ =code.substring(0, i);
break;
}
}
}
return code_;
}
}
5.使用线程调用solr
package com.thinkgem.jeesite.modules.solr.web;
public class AwimgSolrThread implements Runnable{
private List<AdbaResAwimg> lists;
public AwimgSolrThread(List<AdbaResAwimg> list){
this.lists = list;
}
@Override
public void run() {
CreatAwimgSolr creatSolr = SpringContextHolder.getBean(CreatAwimgSolr.class);
creatSolr.saveSolr(lists);
}
}
6、solr的java代码的编写:(对solr进行查)
@SuppressWarnings({ "unchecked", "rawtypes" })
public List<String> query1(Map<String, String> map, int start, int count, Object awimg, SolrTemplate solrTemplate) {
if (map == null) {
return null;
}
System.out.println(map);
List<String> field = Lists.newArrayList(), key = Lists.newArrayList();
Set<String> keySet = map.keySet();
for (String key1 : keySet) {
key.add(key1);
field.add(map.get(key1));
}
System.out.println(key);
// 检测输入是否合法
if (key.size() == 0 ||field.size() == 0 || key.size() != field.size()) {
log.debug("输入不合法");
return null;
}
SolrQuery query = null;
try {
/*List<String> names = getFieldName();
query = new SolrQuery(key.get(0) + ":" + field.get(0));
for (int i = 0; i < key.size(); i++) {
System.out.println(field.get(i));
for(String name : names){
if(field.get(i) != null && key.get(i).equals(name)){
query.addFilterQuery(key.get(i) + ":" + field.get(i));
System.out.println(key.get(i) + ":" + field.get(i));
}else{
log.debug("awimg中没有"+key.get(i)+"该字段");
}
}
}*/
List<String> names = getFieldName();
System.out.println(names);
query = new SolrQuery();
StringBuffer qsb = new StringBuffer();
for(int i = 0; i < key.size(); i++){
if(key.get(i).equals("aucCurrency")){
names.add("aucCurrency");
/* field.add(map.get(key));*/
}
if(key.get(i).equals("aucTurnoverStatus")){
names.add("aucTurnoverStatus");
/*field.add(map.get(key));*/
}
if(key.get(i).equals("orgName")){
names.add("orgName");
}
}
for (int i = 0; i < key.size(); i++) {
for(String name : names){
if(field.get(i) != null && key.get(i).equals(name)){
qsb.append(key.get(i) + ":" + field.get(i)+" AND ");
System.out.println(key.get(i) + ":" + field.get(i)+" AND ");
}
}
if(field.get(i) != null && key.get(i).startsWith("catCode")){
qsb.append("(" + field.get(i)+") AND " );
}
if(field.get(i) != null && key.get(i).startsWith("dcCode")){
/*qsb.append("dcCode"key.get(i).substring(0,key.get(i).length()-1) + ":" + field.get(i)+" OR " );*/
qsb.append("(" + field.get(i)+") AND " );
}
}
String q = qsb.toString();
if(q.length()>4){
q =q.substring(0, q.length()-4);
}
//对获取到的字段进行拼接,拼接为solr可以认识的查询语句。从而查询数据。
System.out.println(q+"*---------");
query.setQuery(q);
query.addFacetQuery("isDefault"+":"+"Y");//判断语言是否为默认,默认为中文。
// 设置起始位置与返回结果数
query.setStart(start);
query.setRows(count);
query.set("fl","sid");
System.out.println(query);
} catch (Exception e) {
e.printStackTrace();
}
SolrServer solrServer = solrTemplate.getSolrServer();
/* SolrServer solrServer = new HttpSolrServer(url);
*/ //solrTemplate.getSolrServer();
QueryResponse queryResponse = null;
try {
queryResponse = solrServer.query(query);
} catch (SolrServerException e) {
e.printStackTrace();
return null;
}
//List<AdbaResAwimg> aracList = Lists.newArrayList();
List<String> sidList = Lists.newArrayList();
// 获取返回的结果
SolrDocumentList docs = queryResponse.getResults();
System.out.println("结果为"+docs);
for (SolrDocument doc : docs) {
System.out.println(doc.toString());
String name = doc.toString();
String[] value = name.split("=");
String[] value1 = value[1].split("}");
System.out.println(value1[0]);
sidList.add(value1[0]);
}
if(sidList.size() == 0){
return null;
}else{
return sidList;
}
//return aracList;
}
//获取类中的字段名
public List<String> getFieldName(){
AdbaResAwimg acore = new AdbaResAwimg();
Field[] fields = acore.getClass().getDeclaredFields();
List<String> fieldNameList = new ArrayList<String>();
String Name = null;
for (int j = 0; j < fields.length; j++) {
fields[j].setAccessible(true);
// 字段名
Name = fields[j].getName();
fieldNameList.add(Name);
}
return fieldNameList;
}
<schema name="example" version="1.5">
name:标识这个schema的名字 version:现在的版本
sortMissingLast和sortMissingFirst两个属性是用在可以内在使用String排序的类型上(包括: string,boolean,sint,slong,sfloat,sdouble,pdate)。
sortMissingLast="true",没有该field的数据排在有该field的数据之后,而不管请求时的排序规则。
sortMissingFirst="true",跟上面倒过来呗。
2个值默认是设置成false
<fields>
<field name="_version_" type="long" indexed="true" stored="true"/>
fields节点内定义具体的字段(类似数据库的字段)
属性:
name:字段名
type:之前定义过的各种FieldType
indexed:是否被索引
stored:是否被存储(如果不需要存储相应字段值,尽量设为false)
multiValued:是否有多个值(对可能存在多值的字段尽量设置为true,避免建索引时抛出错误)
compressed:[false],是否使用gzip压缩(只有TextField和StrField可以压缩)
omitNorms:是否忽略掉Norm,可以节省内存空间,只有全文本field和need an index-time boost的field需要norm。(具体没看懂,注释里有矛盾)
termVectors:[false],当设置true,会存储 term vector。当使用MoreLikeThis,用来作为相似词的field应该存储起来。
termPositions:存储 term vector中的地址信息,会消耗存储开销。
termOffsets:存储 term vector 的偏移量,会消耗存储开销。
default:如果没有属性需要修改,就可以用这个标识下。
<dynamicField name="dcName*" type="text_word" indexed="true" stored="true" multiValued="true"/>
动态字段,没有具体名称的字段,用dynamicField字段,只要是符合“dcName+...”都是符合的字段。
如果一个field的名字没有匹配到,那么就会用动态field试图匹配定义的各种模式。
1)"*"只能出现在模式的最前和最后;2)较长的模式会被先去做匹配;3)如果2个模式同时匹配上,最先定义的优先
<dynamicFieldname="*" type="ignored" multiValued="true" />
如果通过上面的匹配都没找到,可以定义这个,然后定义个type,当String处理。(一般不会发生)
但若不定义,找不到匹配会报错
</fields>
<copyField source="qAllDefaultValue" dest="all"/>
建议建立一个拷贝字段,将所有的 全文本 字段复制到一个字段中,以便进行统一的检索
在添加索引时,将所有被拷贝field(如cat)中的数据拷贝到text field中
作用:1)将多个field的数据放在一起同时搜索,提供速度;2)将一个field的数据拷贝到另一个,可以用2种不同的方式来建立索引。
<uniqueKey>sid</uniqueKey> 唯一的键(文档的唯一标识)
<defaultSearchField>all</defaultSearchField>如果搜索参数中没有指定具体的field,那么这是默认的域。
<solrQueryParser defaultOperator="AND"/>配置搜索参数短语间的逻辑,可以是"AND|OR"。
<types>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
name:就是这个FieldType的名称。
class:指向org.apache.solr.analysis包里面对应的class名称,用来定义这个类型的行为。
<fieldType name="text_chinese_JCSEG" class="solr.TextField">
自己定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤,
<analyzer type="index">
这个分词包是空格分词,在向索引库添加text类型的索引时,Solr会首先用空格进行分词
然后把分词结果依次使用指定的过滤器进行过滤,最后剩下的结果,才会加入到索引库中以备查询。
注意:Solr的analysis包并没有带支持中文的包,需要自己添加中文分词器,google下。
<tokenizer class="org.lionsoul.jcseg.solr.JcsegTokenizerFactory" mode="complex"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.lionsoul.jcseg.solr.JcsegTokenizerFactory" mode="complex"/>
</analyzer>
</fieldType>
如何写solr代码?
1、编写solr每次读取的条数
2、开始运行run方法,运行saveSolrEntity方法
3、判断service和adbaresrelationservice是否为空。若为空,给其赋值。
4、判段class名,是否为空
5、使用redis,根据class名称得到所有key值,(通过相似值)
6、判断值是否为空,若为空,则输出为空结果
7、否则有数据,则开始跑索引,初始化数据
8、设置数据的总共数据,条数。开始数
9、得到对象的工厂,为空则返回
10、不为空,则开始索引数据
11、创建集合数组saveLIst,开始遍历数据,得到每一条数据,判断的到的数据id是否为空,不为空则用:分割,,=2,则输出id,
12、吧class转换为map
13、 转换数据为 entityCore
14、复制map到entitycore
15。把entitycore数据复制到savelist
16、创建索引
17,吧savelist保存到solr库中
18、得到的数据条数+10000,判断得到的数据是否小于总数,是,则输出实际得到的数据条数
19、否则,创建索引,失败
solr软硬提交的区别:
- 硬提交: solrService.commit(true,true,true)
其中硬提交是提交数据持久化到磁盘里面,并且能够查询到这条数据。
按照下面的配置就会使用solr的自动硬提交功能,就不用我们自己手动提交。
<autoCommit> <!--表示软提交达到1万条的时候会自动进行一次硬提交--> <maxDocs>10000</maxDocs> <!--表示软提交10秒之后会执行一次硬提交--> <maxTime>10000</maxTime> <!--true表示每一次硬提交都开启一个新的Searcher--> <openSearcher>false</openSearcher> </autoCommit>
- 软提交: solrService.commit()
其中软提交是提交数据到内存里面,并没有持久化到磁盘,但是他会把提交的记录写到tlog的日志文件里面
下面就是自动软提交的配置,不需要自己维护提交(默认没有开启):
<autoSoftCommit> <!--5秒执行一次软提交--> <maxTime>5000</maxTime> </autoSoftCommit>
注意:如果我们索引了数据并且没有做任何提交,它也会在tlog日志文件中做记录。并且在正常关闭solr 服务的时候,solr会自动执行一次硬提交,在solr 重启的时候会自动加载tlog的日志文件。
为了方便管理员和工程师调整Solr的配置和访问在线文档和其他的帮助,Solr提供了一个Web界面去查看Solr的配置详情,运行查询语句和分析文档字段。这个界面在第三篇里面提到过就是管理员界面(以下简称Admin UI),如下图所示:
可以看出Admin UI的界面还是比较复杂的。下面将分别就界面的各个模块进行讲解。
获取帮助
在右侧区域的底部,就是帮助区,无论当前正在Admin UI上操作什么,帮助区的位置始终不变并且一直显示。如下表:
链接 |
描述 |
Documentation |
导航到Solr的在线文档页面。 |
Issue Tracker |
导航到Apache Solr项目的JIRA问题跟踪服务器。服务地址: |
IRC Channel |
导航到Apache的维基百科页面,描述如何加入Solr的IRC在线聊天室: |
Community forum |
导航到Apache的维基百科页面,这里有关于加入Solr社区邮件列表的更多信息。 |
Solr Query Syntax |
导航到Guide文档的Query Syntax and Parsing小节。 |
日志
日志页面显示当前Solr节点最近记录的信息。点击Admin UI左侧的Logging链接,就能看到下图类似的页面。
设置日志的级别
当选中Logging下的Level链接时,将会看到一个classpath和classname的层级结构。点击任意一行,都会弹出一个日志级别的菜单,可以设置任意级别或取消级别设置。因为日志设置是树状的,设置了父节点的日志级别,将会默认的作用到其子节点,除非子节点有特定的设置。如图所示,root下的所有节点默认都是INFO级别,但是hadoop节点将只会输出WARN级别的日志。
Core Admin
Core Admin界面提供了一些管理Core级别信息的基础功能,并且由Core Admin API驱动。在Core Admin界面(如下图)中,左侧是一个已经存在的Core的列表,点击任意一个Core名称,可以进而查看它的详细信息,同时还能完成各种操作。
Java Properties
Java Properties界面,提供到Solr系统中最高效率的必备组件的简单访问。在这个界面,我们能看到运行着Solr的JVM的所有的属性:包括class path,文件编码,JVM内存设置,操作系统等等。
Thread Dump(线程堆栈)
线程堆栈界面,能使你检查服务器上当前的活跃线程。每一个线程都被展示在列表中,而且对于堆栈轨迹的访问查看也是可以的。
线程名称左边的图标,用于指示线程的状态,例如:打勾的表示的是“可运行状态”;线程名称右边的乡下的箭头,用于指示可以展开查看堆栈轨迹。当移动指针到线程名称上面的时候,线程状态将显示出来。有下面这样一些线程状态:
状态 |
意义 |
NEW |
线程未启动。 |
RUNNABLE |
线程正在JVM上运行。 |
BLOCKED |
线程被监视器锁阻塞。 |
WAITING |
线程无限期的等待另一个线程完成一个特定的动作。 |
TIMED_WAITING |
线程等待另一个线程完成一个动作来指定一个等待时间。 |
TERMINATED |
线程已经退出。 |
Core Selector
点击Core Selector菜单,将会显示一个当前Solr实例中的Core的列表;如果Core过多,还可以通过列表上方的搜索框对特定的Core进行搜索。当选中一个Core之后,内容区域将会展示Core对应的元数据,同时在Core选择框下面,会出现一个二级菜单。
二级菜单如下:
- Overview:选择Core之后呈现的默认界面,展示Core的统计信息、实例信息、同步复制等信息。
- Analysis:分析从指定字段找到的数据。
- Dataimport:显示Data Import Handler当前的状态信息。
- Documents:提供一个简单的表单,让你可以通过浏览器直接执行许多Solr的索引命令。
- Files:显示当前Core的配置文件。
- Ping:检测服务器的可链接情况。
- Plugins/Stats:查看Core的插件及统计状态信息。
- Query:使得你可以提交一个关于Core中多个元素的结构化查询。
- Replication:展示主从复制的基本信息。并且可以完成简单的设置。
- Schema:显示模式的基本信息。可以添加字段、动态字段和拷贝字段。
- Segmetns info:查看分片信息。
Analysis(分析界面)
分析界面使得你可以检查怎样根据Schema中设置的字段、字段类型和动态字段配置来处理数据。你可以同时分析内容在建索引时和处理查询时会被如何处理以及单独查看结果。理想状况下,你可能希望内容能始终如一的处理,并且此界面允许你验证字段和字段分析链的设置。
在下图顶部的一个或两个输入框中都输入内容,然后选择将要分析的字段名或字段类型。勾选Verbose Output将会看到更多的输出信息。
Dataimport(数据导入界面)
数据导入界面展示DataImportHandler的配置,并且允许你启动和监测导入命令的状态。倒入命令的定义见下图中间区域。此界面同时让你可以调整选项内容去控制如何把数据倒入到Solr,查看控制倒入的配置文件。
Documents(文档界面)
文档界面提供了一个简单的表单,允许你可以执行许多Solr的索引命令,而且支持数种文档格式(如:JSON,XML,CSV等),甚至支持上传对应格式的文档。
第一步是定义RequestHandler,又叫做‘qt’。默认情况下使用/update,如果要使用Solr Cell,将命令改为/update/extract。接着选择文档类型,选择文档类型后,下面的参数将会发生改变。
JSON
当使用JSON文档类型,就像在命令行使用RequestHandler一样。不同的是,在Documents文本框中录入文档,而不是在命令行中录入,但是文档的结构还应该是JSON类型。然后确定文档应该什么时候添加到索引中(Commit Within),无论是否已经存在相同id的文档需要被覆盖(如果不允许覆盖,那么新加入的文档将被删除),最后提交文档。
CSV
当使用CSV文档类型,和命令行使用RequestHandler也是一样的。不同的是,在Documents文本框中录入文档,而不是在命令行中录入,但是文档的格式是CSV格式的。然后确定文档应该什么时候添加到索引中(Commit Within),无论是否已经存在相同id的文档需要被覆盖(如果不允许覆盖,那么新加入的文档将被删除),最后提交文档。
File Upload
File Upload选项,允许上传一个已经准备好的文件。如果只是用/update命令,上传文档的格式限制在XML,CSV和JSON格式。
Solr命令
Solr命令选项允许使用XML或JSON执行指定动作。例如定义添加或删除文档,更新文档的指定字段,提交和优化索引的命令。当使用/update命令的时候,文档要按需格式化。
XML
当使用XML文档类型,和命令行使用RequestHandler也是一样的。不同的是,在Documents文本框中录入文档,而不是在命令行中录入,但是文档的格式是XML格式的,每个文档都需要用<doc>标签分割,在<doc>标签内定义字段。然后确定文档应该什么时候添加到索引中(Commit Within),无论是否已经存在相同id的文档需要被覆盖(如果不允许覆盖,那么新加入的文档将被删除),最后提交文档。
文件界面
在文档界面,我们可以查看选中集合或Core的配置文件(诸如solrconfig.xml和Schema文件等)。solrconfig.xml文件定义了Solr索引内容和查询响应的行为。Schema允许定义文档的字段类型、定义文档的字段以及动态字段。其他的配置文件通常都依赖于它们如何引用solrconfig.xml或Schema文件。
在此界面中不能编辑配置文件,要编辑配置文件,需要使用其他文本编辑器。
Query(查询界面)
在查询界面可以提交一个查询请求到Solr集合(或者Core),并且分析结果。在下图的示例中,已经提交了一个默认的查询,右侧部分显示的是查询结果。右侧顶部展示完整的查询http请求(可以在其它编程语言中使用该请求完成跨平台的查询)。
查询界面有很多的查询字段或参数。如下表:
字段 |
描述 |
Request-handler(qt) |
为请求指定查询处理器(query handler)。如果为指定查询处理器,Solr将使用标准查询处理器来处理响应。 |
q |
查询事件。详细的查询参数将在后面介绍。 |
fq |
过滤查询。 |
sort |
对查询结果按照正序或者倒序排列,排序依据响应的分数或者指定的字符。 |
start,rows |
start是查询结果的偏移量,默认是0,意味着会从第一个查询到的结果返回。rows指示返回结果的行的数量。 |
fl |
定义结果文档的字段。可以显示的指定字段,默认情况下返回所有字段。通过指定字段名的序列,以逗号(,)或空格( )分割。 |
wt |
指定返回结果的格式(jsonxmlpython ubyphpcsv)。 |
indent |
选中该选项,以表明对查询结果进行缩进显示。可以提高结果的可读性。 |
debugQuery |
选中该选项,查询结果将增加Debug信息,包括每个文档的Explain info。 |
dismax |
选中该选项,Dismax查询解析可用。 |
edismax |
选中该选项,Extended查询解析可用。 |
hl |
选中该选项,高亮查询结果。 |
facet |
选中该选项,允许分段查询。 |
spatial |
选中该选项,允许使用位置数据。 |
spellcheck |
选中该选项,启用语法验证。 |
以上是关于solr总结的主要内容,如果未能解决你的问题,请参考以下文章