solr版本4.10.2
solr删除全部索引数据:选择Document Type为XML类型
<delete><query>*:*</query></delete><commit/>
从数据库导入多表到solr中,由于solr规定每一条记录必须有一个主键值,用来唯一标识一条索引的记录,默认是使用id字段来作主键,所以多表情况下会出现id重复,导致记录被覆盖,因此将solr的id设为自生成uuid,由solr维护。
1、在schema.xml文件中添加:
<fieldType name="uuid" class="solr.UUIDField" indexed="true" />
2、设置主键id的type为uuid:
<field name="id" type="uuid" indexed="true" stored="true" required="false" multiValued="false" />
3、在solrconfig.xml文件中添加:
<updateRequestProcessorChain name="uuid">
<processor class="solr.UUIDUpdateProcessorFactory">
<str name="fieldName">id</str>
</processor>
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
4、将此requestHandler中的defaults修改为如下:
<requestHandler name="/update" class="solr.UpdateRequestHandler">
<lst name="defaults">
<str name="update.chain">uuid</str>
</lst>
</requestHandler>
5、注释下面的代码,不然会报异常:
<searchComponent name="elevator" class="solr.QueryElevationComponent" >
<str name="queryFieldType">string</str>
<str name="config-file">elevate.xml</str>
</searchComponent>
6、将<str name="update.chain">uuid</str>
加入到数据导入的部分:
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">db-data-config.xml</str>
<str name="update.chain">uuid</str>
</lst>
</requestHandler>
这样,在db-data-config.xml中就不需要指定solr中id对应的column。
这是我的多数据源配置,对于oracle数据库要注意字段大写:
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<dataSource
name="mysql"
type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/youmanagerdb"
user="root"
password="root"/>
<dataSource
name="oracle"
type="JdbcDataSource"
driver="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@//127.0.0.1:1521/orcl"
user="flyy3"
password="flyy3"/>
<document>
<entity name="bill" dataSource="mysql" query="select mybill_id,memo,money from tbl_mybill">
<field column="mybill_id" name="bill_id" />
<field column="memo" name="bill_memo" />
<field column="money" name="bill_money" />
</entity>
<entity name="schedulejob" dataSource="mysql" query="select job_id,memo,cron_expression from tbl_schedulejob">
<field column="job_id" name="schedulejob_id" />
<field column="memo" name="schedulejob_memo" />
<field column="cron_expression" name="schedulejob_cron" />
</entity>
<entity name="cpws" dataSource="oracle" transformer="ClobTransformer" query="select ID, AJLB, NR from cpws where rownum<200">
<field column="ID" name="cpws_id" />
<field column="AJLB" name="cpws_ajlb" />
<field column="NR" name="cpws_nr" clob="true"/>
</entity>
</document>
</dataConfig>
对于clob字段,需要加上transformer="ClobTransformer"
和clob="true"
如果涉及到多表的,使用别名作为name,如下(之前使用表名+字段名作为name,就无法导入数据):
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<dataSource
name="oracle"
type="JdbcDataSource"
driver="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@//192.168.30.172:1521/orcl"
user="flyy3"
password="flyy3"/>
<document>
<entity name="flqw" dataSource="oracle" transformer="ClobTransformer" query="SELECT
FLQWJBXX.ID as FID, FLQWJBXX.MC as FMC, FLQWJBXX.BBH as FBBH, FLQWJBXX.BBBM as FFBBH, FLQWJBXX.BBRQ as FBBRQ, FLQWJBXX.SSRQ as FSSRQ,
FLQWJBXX.YXX as FYXX, FLQWJBXX.FLFL_ID as FLFLID, FLFL.MC as FLFLMC, FLFL.GFLFL as FGFLFL, FLFL.SJFLFLID as FSJFLFLID, FLQWNR.NR as FNR
FROM FLQWJBXX, FLFL, FLQWNR WHERE
FLQWJBXX.ID = FLQWNR.ID AND FLQWJBXX.FLFL_ID = FLFL.ID">
<field column="FID" name="flqw_flqwjbxx_id" />
<field column="FMC" name="flqw_flqwjbxx_mc" />
<field column="FBBH" name="flqw_flqwjbxx_bbh" />
<field column="FBBBM" name="flqw_flqwjbxx_bbbm" />
<field column="FBBRQ" name="flqw_flqwjbxx_bbrq" />
<field column="FSSRQ" name="flqw_flqwjbxx_ssrq" />
<field column="FYXX" name="flqw_flqwjbxx_yxx" />
<field column="FLFLID" name="flqw_flqwjbxx_flfl_id" />
<field column="FLFLMC" name="flqw_flfl_mc" />
<field column="FGFLFL" name="flqw_flfl_gflfl" />
<field column="FSJFLFLID" name="flqw_flfl_sjflflid" />
<field column="FNR" name="flqw_flqwnr_nr" clob="true"/>
</entity>
</document>
</dataConfig>
solr的join用法:
因为工作中需要把多张表放在solr中加快查询速度,同时这几张表又涉及到多表关联查询,在网上看到说join可以做到这点。但关于join的资料很少,规则也不是很明白,下面是我个人的一点理解:
sq.set("q", "{!join from=id to=name}title:2");
相当于sql语句:
select * from tbl1 where name in (select id from tbl2 where title = 2)
sq.set("q", "{!join from=id to=title fromIndex=core3}name:apple");
相当于slq语句:
select f.* from tbl4 f inner join tbl3 t on t.id = f.title where t.name = 'apple'
tbl3相当于core3,tbl4相当于core4
在linux上部署solr时,遇到一个小坑:
我在windows上部署,是在tomcat的start.bat中指定solr_home的位置。但是在linux上并不使用start.bat,而是start.sh,在这个文件我不知道怎么指定solr_home的位置,于是就在solr的web.xml中加入如下代码:
<env-entry>
<env-entry-name>solr/home</env-entry-name>
<env-entry-value>/data/solr/solr_home</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>
在做不包含查询时,使用的是:
-flqw_flqwnr_nr:美国 AND -flqw_flqwnr_nr:相关
网上的方式:
flqw_flqwnr_nr:* NOT 美国 NOT 相关
这种方式失效。
其他查询的写法也相似:
flqw_flqwnr_nr:美国 OR flqw_flqwnr_nr:中国
flqw_flqwnr_nr:(美国 OR 中国)
如果要让搜索字在查询时不分词,就用"
来包裹搜索字,如下:
params.set("q", "flqw_flqwnr_nr:"+'"'+"全国人民代表大会"+'"');
项目中需要根据查询条件和类别获取各个分类的查询结果数量,我使用的是group分组查询,在查询条件时,一开始我设置的是如果用户没有输入搜索词,那么就
params.set("q", "nr:*");
结果查询速度相当慢,然后根据逻辑改成了
params.set("q", "*:*");
速度就快了很多。
网上提到solr索引这块,可以用int或long类型的,就不要用string,原因是整型的索引存储空间一般比字段串所占的存储索引空间要小;整型的查找比较速度比字段串类型要快。
关于solr分页这块,假如数据有100万条,直接查询最后一页,速度会相当慢,这就类似于mysql中的分页
select * from table where column between 1 and 2 order by id limit 0, 10;
select * from table where column between 1 and 2 order by id limit 1000000, 10;
mysql在执行时,会扫过满足结果的前start行的记录,然后才读取len行的数据,如果start特别大,会非常慢。
在solr中也会出现这种情况,现在的思路是:
假如是通过order by进行id asc排序,对于100万条数据,如果用户查询的是前50万条,就正常查询;如果用户查询的是后半部分数据,就id desc排序,根据总条数和用户点击的页码计算出逆序排序后的起始数,获得查询结果后再倒序回来。