线上业务准备使用solr做数据存放和索引的功能,其中有的字段要求会存入多个字,solr的field的
multivalue可以实现这个功能。
|
1
|
<
dynamicField
name
=
"*_ss"
type
=
"string"
indexed
=
"true"
stored
=
"true"
multiValued
=
"true"
/>
|
下面看看其实现原理:
和solr的写入document相关的两个类是SolrInputDocument 和SolrInputField,其中SolrInputDocument 是和整条document有关,SolrInputField 是和field相关(属性包含field的名称,值和boost值)。
SolrInputDocument 类中和document添加的方法主要有addField 和setField,其中setField是覆盖前面的value,addField是追加value.
看看其具体实现:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
SolrInputDocument() {
_fields =
new
LinkedHashMap <String,SolrInputField>();
// 通过构造方法构建一个map,value是SolrInputField
}
private
final
Map<String,SolrInputField> _fields;
public
void
addField(String name, Object value,
float
boost )
//addFiled的方法中,参数value是个object
SolrInputField field = _fields.get( name );
// name是指field的名称,value是指field的值,判断map中是否已经有这个field的信息
if
( field ==
null
|| field.value ==
null
) {
// 如果filed或者filed value为空,就用本类的setField(即第一次添加有效地值,类似于overwrite)
setField(name, value, boost);
}
else
{
field.addValue( value, boost );
// 否则用SolrInputField的addValue方法(类似于append)
}
}
|
其中setField的实现如下:
|
1
2
3
4
5
6
|
public
void
setField(String name, Object value,
float
boost )
{
SolrInputField field =
new
SolrInputField( name );
_fields.put( name, field );
field.setValue( value, boost );
//其实是调用了SolrInputField的setValue方法
}
|
再来看看SolrInputField类:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public
class
SolrInputField
implements
Iterable<Object>, Serializable
{
String name;
Object value =
null
;
float
boost =
1
.0f;
public
SolrInputField( String n )
{
this
. name = n;
}
public
void
setValue(Object v,
float
b) {
boost = b;
if
( v
instanceof
Object[] ) {
// Arrays will be converted to a collection.如果传入的value是个list,会转换为collection
Object[] arr = (Object[])v;
Collection<Object> c =
new
ArrayList<Object>( arr.length );
for
( Object o : arr ) {
c.add( o );
}
value = c;
}
else
{
value = v;
}
}
public
void
addValue(Object v,
float
b) {
//可以看到同样会判断是否为collection
if
( value ==
null
) {
if
( v
instanceof
Collection ) {
Collection<Object> c =
new
ArrayList<Object>(
3
);
for
( Object o : (Collection<Object>)v ) {
c.add( o );
}
setValue(c, b);
}
else
{
setValue(v, b);
}
return
;
}
|
....
通过上面可以看出,在向field传入value的时候,是可以传入数组这种数据结构的,这样,就可以在一个field里面插入多个value
比如下面的两种方法,都可以写入同一个field多个有效值:
例1:
|
1
2
3
4
5
6
|
SolrInputDocument doc =
new
SolrInputDocument();
String key =
"123"
;
doc.addField(
"id"
, key);
doc.addField(
"test_ss"
,
"vv1"
);
doc.addField(
"test_ss"
,
"vv2"
);
doc.addField(
"test_ss"
,
"vv3"
);
|
例2:
|
1
2
3
4
5
|
SolrInputDocument doc =
new
SolrInputDocument();
String key =
"123"
;
String[] vv = {
"vv1"
,
"vv2"
,
"vv3"
};
doc.addField(
"id"
, key);
doc.addField(
"test_ss"
, vv);
|
注意,每次实例化一个SolrInputDocument 的对象,都相当于对这一行进行重新overwrite的操作,因为solr是基于lucene的,lucene的update是通过delete+add实现的。也就是如果一个document为id:1,test_ss:aa,在后面重新实例化后,对于相同的id记录,使用addFiled("test_ss","bb")之后document变为id:1,test_ss:bb了。。(setField的覆盖和addField的追加都是对本次实例说的)。
本文转自菜菜光 51CTO博客,原文链接:http://blog.51cto.com/caiguangguang/1433761,如需转载请自行联系原作者