前段时间我一直在参与中台业务的solr服务,因为也是第一次接触,在学习的过程中做了一些笔记,正好在这里做一个记录。
我们这里就直接从managed-schema说起。
一、Field
managed-schema文件主要就是用来配置Field,Field相当于Java中的类属性,你可以给它配置各种属性,比如是否需要显示呀,是否可以作为被检索的索引呀等等。
我们找一个来看看都有哪些属性。
<field name="id" type="text_ik" indexed="true" stored="true" multiValued=”true”/>
1.name:是查询时的名称。
2.type:字段类型。
3.indexed:是否为索引字段。(true:是。false:否)solr控制台使用df当作查询域。注:indexed=true,即可以使得一个filed当作搜索条件。indexed=false,即此field无法被当作搜索的条件。
我们找一个indexed=true的字段试试,就用id吧。
显然,我们找到一个检索结果。从第一张图里我们可以看到,url的indexed=false,所以应该是无法用url检索消息的。我们就直接用这条数据的url作为检索的条件,看能不能检索到该条数据。
显然,啥玩意也没有。
4.stored:是否存储。solr控制台使用fl当作查询结果。
注:stored=true,则此filed可以作为查询结果。
stored=false,则即使你有符合的数据,你也看不到该field。
从上图可知,province字段 indexed=true,但是stroed=false。这就说明,你可以用province作为检索条件,但是你的检索结果不会显示出来。我们来试试。(我们的province用的是编码,以山西为例)
ok,从以上的查询结果,我们可以看出来,province的确可以作为检索条件,但是在检索出来的结果中并不会显示province这个字段。
5.multiValued:是否多值(一般配合copyFiled使用)
如果对filed域的其它属性感兴趣,可以参考:https://www.cnblogs.com/langfanyun/p/5868182.html。这篇文章将所有的属性弄成了表格,我觉得ok。
这里放一张缩略:
二、copyField 复制域
三、multivalued 多值
<field name="allcontent" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="title" dest="allcontent" />
<copyField source="orgtitle" dest="allcontent" />
<copyField source="content" dest="allcontent" />
从上文看出allcontent区域,是title、orgtitle、content三个的集合,无论搜索title、orgtitle、content任意一个,都能通过allcontent搜索出来。
其中allcontent 本身也是一个域,也可存储信息。其最终结果为 title+orgtitle+content+allcontent 本身。
所以,当我们需要对标题检索的时候可以直接用title作为检索条件,如果对多个域进行检索,比如我希望title+content+orgtitle这三个字段中只要有一个字段中含有某关键词,那么就可以用multivalued,配置一下多值即可。
此外,除了可以多值检索,它还可以设置权重。 参考https://blog.csdn.net/u010248330/article/details/72961551。
关于solr多字段搜索,排序打分规则,可以参考https://www.iteye.com/blog/adminjun-2258480。这两篇都很详细。这里也就不赘述了。
四、dynamicField 动态域
业务场景:并不是我们业务的所有字段都需要在schema.xml、managed-schema指定成固定的字段。
<field name="name" type="string" indexed="true" stored="true"/>、
<field name="sex" type="string" indexed="true" stored="true"/>
这些都是固定的。
例如我现在有一个新业务,大概有5个字段,需要拼接在原来的core里面,那么dynamicField就发挥了它的用武之地了。
直接上代码:
schema.xml、managed-schema文件中的配置如下
<!-- 动态字段 -->
<dynamicField name="solrField_s_*" type="text_general_rev" indexed="true" stored="true"/> 存放String类型
<dynamicField name="solrField_d_*" type="double" indexed="true" stored="true"/> 存放double类型
<dynamicField name="solrField_l_*" type="long" indexed="true" stored="true"/> 存放long类型
java代码:
// 得到请求
SolrClient sc = getSolrClient();
// 拼装文本
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", 1);
doc.addField("solrField_s_1", "1");
doc.addField("solrField_s_2", "2");
doc.addField("solrField_d_1", "2.0");
doc.addField("solrField_l_1", "1239012320");
sc.add(doc);
sc.commit();
查询结果:
{
"responseHeader":{
"status":0,
"QTime":135,
"params":{
"q":"*:*",
"indent":"on",
"wt":"json",
"_":"1510043041895"}},
"response":{"numFound":1,"start":0,"docs":[
{
"id":1,
"solrField_s_1":"1",
"keywords":["1",
"2",
"2.0",
"1239012320"],
"solrField_s_2":"2",
"solrField_d_1":2.0,
"solrField_l_1":1239012320,
"_version_":1583395999953453056}]
}}
通过结果可以看出,我的schema.xml里面根本就没配置solrField_s_1,solrField_s_2,solrField_d_1,solrField_l_1这些字段,但是却能把数据放进去,既然放进去了,那么肯定也就可以根据对应的字段进行查询。
不过这里说一下,动态域用是好用,但是这种东西必然会增加你的维护成本,所以看着用吧。
五、solr的配置IK分词器
这个我在后面的文章会有详细的介绍其原理及其使用,先占一个坑。
六、<uniqueKey>id</uniqueKey>
来判断数据的唯一性。类似于数据库的id。
如果id在索引中已经存在,则更新索引。否则插入索引。删除索引也是按照这个去判断,下文会讲。
七、控制台
reload:单机环境下,修改完配置文件后,可以不重启服务,直接点击reload会重新加载配置文件。
optimize :optimize有点像硬盘上整理磁盘碎片的操作。为了提高搜索速度,它会将索引重组在一起,然后移除需要被删除或是更新的文档。这里需要注意一下,solr是没有update的这种操作,只有增加删除。solr在优化的时候,将需要删除或者是需要被替换的索引标记为deleted。然后再创建新的文档,替换掉需要被替换的。optimize就是执行此操作。因此,再优化的时候,你的索引会先增大,然后再减小。optimize操作会创建一个全新的索引结构,因此,你大概需要预备出二倍于你commit时索引大小的空间,否则会影响你solr的正常服务。
八、java使用solr增删改查
增加、修改索引。solr会动态根据id。来判断是更新,还是插入。
删除索引
这里需要注意一下,<commit/>语句必不可少。
1.控制台删除
删除core下全部索引:
<delete><query>*:*</query></delete>
<commit/>
删除指定索引:
<delete><query>id:1</query></delete>
<commit/>
2.Java代码
solrServer.deleteByQuery("*:*");
第一篇就先到这,如果有哪些地方写的不对,或者没有描述准确,欢迎大家留言指正,多谢。