本节我给大家测试一下Linux环境的Solr,通过增删改查的实例demo看看Solr环境是否已经OK。记得有哥们留言,问到只看见Solr和Cassandra的单独环境搭建,却不见它们的协同。我想说这两个没有什么必然的联系,在Cassandra的DSE版本,在Cassandra的内部继承了一套Solr的环境,只需要开启开关,就可以自动往Solr同步数据。但是这个嵌入的版本性能太差,无法使用。那么它们之间要怎么样联系呢?因为cassandra的二级索引查询速度不尽如人意,而且查询的语法有限,所以我们引入Solr,用Solr查询出主键,再去Cassandra根据主键查询出想要的速度,总结来说就是Solr中存储一些用于查询的字段,而Cassandra中存储所有要用到的数据,Solr负责查询,Cassandra集群负责数据。
这两天在使用Solr的时候碰到一个问题,由于我的Schema定义如下
当时我少定义了一个uniqueKey,结果报错,但是我加上后重启Tomcat,还是报这个错误,后来一直没解决掉。第二天,我发现居然自己好了,于是看了一下Tomcat的bin目录,没有shutdown.sh,只有startup.sh。我想着是不是因为没有shutdown的原因,我就采用kill进程的方式,关闭了一下tomcat,然后重启,发现就是因为没有关闭tomcat的原因。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@bogon ~]
# ps -ef |grep tomcat
root 5079 1 3 23:02 ? 00:00:20
/usr/java/jdk1
.7.0_21
/bin/java
-Djava.util.logging.config.
file
=
/usr/apache-tomcat-7
.0.40
/conf/logging
.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.
dirs
=
/usr/apache-tomcat-7
.0.40
/endorsed
-classpath
/usr/apache-tomcat-7
.0.40
/bin/bootstrap
.jar:
/usr/apache-tomcat-7
.0.40
/bin/tomcat-juli
.jar -Dcatalina.base=
/usr/apache-tomcat-7
.0.40 -Dcatalina.home=
/usr/apache-tomcat-7
.0.40 -Djava.io.tmpdir=
/usr/apache-tomcat-7
.0.40
/temp
org.apache.catalina.startup.Bootstrap start
root 6128 6093 0 23:12 pts
/0
00:00:00
grep
tomcat
[root@bogon ~]
# kill -9 5079
[root@bogon ~]
# cd /usr
[root@bogon usr]
# cd apache-tomcat-7.0.40
[root@bogon apache-tomcat-7.0.40]
# cd bin
[root@bogon bin]
# sh startup.sh
Using CATALINA_BASE:
/usr/apache-tomcat-7
.0.40
Using CATALINA_HOME:
/usr/apache-tomcat-7
.0.40
Using CATALINA_TMPDIR:
/usr/apache-tomcat-7
.0.40
/temp
Using JRE_HOME:
/usr/java/jdk1
.7.0_21
Using CLASSPATH:
/usr/apache-tomcat-7
.0.40
/bin/bootstrap
.jar:
/usr/apache-tomcat-7
.0.40
/bin/tomcat-juli
.jar
|
OK,既然没有问题,我们进入正题,修改Sol实例目录下的SolrConfig.xml文件中的内容
1
2
3
|
<
cores
adminPath
=
"/admin/cores"
defaultCoreName
=
"MyTest.UserInfo"
host
=
"${host:}"
hostPort
=
"${jetty.port:8080}"
hostContext
=
"${hostContext:solr}"
zkClientTimeout
=
"${zkClientTimeout:15000}"
>
<
core
name
=
"MyTest.UserInfo"
instanceDir
=
"Test"
/>
</
cores
>
|
Core Name设置为MyTest.UserInfo。
OK,重新启动Solr,我们打开浏览器,如下
我们实例名称已经成为刚才设置的名称(MyTest.UserInfo)。
接下来我们要看的是我们的程序
Entity下面是我们定义的Solr实体,如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
namespace
SolrCURDDemo
{
using
SolrNet;
using
SolrNet.Attributes;
public
class
UserInfoEntity
{
public
UserInfoEntity() { }
[SolrUniqueKey(
"UserNO"
)]
public
string
UserNO {
get
;
set
; }
[SolrField(
"Name"
)]
public
string
Name {
get
;
set
; }
[SolrField(
"Age"
)]
public
int
? Age {
get
;
set
; }
[SolrField(
"IsMarried"
)]
public
bool
? IsMarried {
get
;
set
; }
}
}
|
和我们刚才定义的Solr Schema一致。然后Reference下面是我们要引用的dll,SolrNet.dll和Microsoft.Practises.ServiceLocation.dl。我下载的SolrNet是0.4.0.2002,大家在网上自己去下。
接下来是我们的SolrConfig配置文件,这个是我自定义的一个xml文件
1
2
3
4
5
6
7
8
9
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
SolrConfigCollection
>
<
SolrConfigs
baseAddress
=
"Http://192.168.192.128:8080/MyTest."
>
<
Schema
name
=
"UserInfo"
entityName
=
"SolrCURDDemo.UserInfoEntity"
></
Schema
>
</
SolrConfigs
>
<!--<SolrConfigs baseAddress="Http://192.168.192.128:8080/MyOtherTest.">
<Schema name="UserInfo"></Schema>
</SolrConfigs>-->
</
SolrConfigCollection
>
|
什么意思呢?在这里我的意思是 一个地址可以有多个Schema,或者多个地址,假如我有这样的一个需求,一个Solr服务负责学生的基信息,一个Solr服务负责学生的成绩信息,那么我们就配置两个SolrConfigs。
接下来是我们Utility,主要是SolrHelper和SolrCollection类
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
|
namespace
SolrCURDDemo
{
using
SolrNet;
using
Microsoft.Practices.ServiceLocation;
using
System.Reflection;
using
SolrNet.Commands.Parameters;
using
System.Configuration;
public
class
SolrHelper
{
private
static
bool
isRegister;
private
static
SolrHelper solrHelper =
new
SolrHelper();
private
SolrHelper()
{ }
private
static
int
MaxQueryCount
{
get
{
return
int
.Parse(ConfigurationManager.AppSettings[
"MaxQueryCount"
].ToString());
}
}
public
static
SolrHelper GetInstance()
{
if
(!isRegister)
{
RegisterSolrInstance();
isRegister =
true
;
}
return
solrHelper;
}
private
static
void
RegisterSolrInstance()
{
string
path = AppDomain.CurrentDomain.BaseDirectory +
@"\SolrConfig\SolrConfig.xml"
;
SolrCollection solrCollection = Deserialize<SolrCollection>(path);
Type startUpType =
typeof
(Startup);
foreach
(SolrConfigs solrConfig
in
solrCollection.SolrConfigs)
{
foreach
(SchemaInfo schema
in
solrConfig.Schemas)
{
MethodInfo method = startUpType.GetMethod(
"Init"
,
new
Type[] {
typeof
(
string
) })
.MakeGenericMethod(Type.GetType(schema.EntityType));
method.Invoke(
null
,
new
object
[] { solrConfig.BaseAddress + schema.ServiceName });
}
}
}
private
static
T Deserialize<T>(
string
path)
where
T :
class
,
new
()
{
XmlReader xmlReader = XmlReader.Create(path);
XmlSerializer xmlSer =
new
XmlSerializer(
typeof
(SolrCollection));
object
deSerializeObj = xmlSer.Deserialize(xmlReader);
xmlReader.Close();
return
deSerializeObj
as
T;
}
private
ISolrOperations<T> GetSolrOperation<T>()
{
return
ServiceLocator.Current.GetInstance<ISolrOperations<T>>();
}
#region solr operations
#region query
public
List<T> QueryByFilter<T>(
string
filter)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
SolrQueryResults<T> result = solrOperation.Query(filter);
return
result.ToList();
}
catch
(Exception ex)
{
throw
ex;
}
}
public
List<T> QueryByFilter<T>(ISolrQuery solrQuery)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
SolrQueryResults<T> result = solrOperation.Query(solrQuery);
return
result.ToList();
}
catch
(Exception ex)
{
throw
ex;
}
}
public
List<T> QueryByFilter<T>(
string
filter, Dictionary<
string
,
string
> sortDictionary)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
List<SortOrder> sortOrderList =
new
List<SortOrder>();
foreach
(KeyValuePair<
string
,
string
> sortPair
in
sortDictionary)
{
SortOrder sortOrder =
new
SortOrder(sortPair.Key, (Order)Enum.Parse(
typeof
(Order), sortPair.Value));
sortOrderList.Add(sortOrder);
}
SolrQueryResults<T> result = solrOperation.Query(filter, sortOrderList);
return
result.ToList();
}
catch
(Exception ex)
{
throw
ex;
}
}
public
List<T> QueryByFilter<T>(ISolrQuery solrQuery, Dictionary<
string
,
string
> sortDictionary)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
List<SortOrder> sortOrderList =
new
List<SortOrder>();
foreach
(KeyValuePair<
string
,
string
> sortPair
in
sortDictionary)
{
SortOrder sortOrder =
new
SortOrder(sortPair.Key, (Order)Enum.Parse(
typeof
(Order), sortPair.Value));
sortOrderList.Add(sortOrder);
}
SolrQueryResults<T> result = solrOperation.Query(solrQuery, sortOrderList);
return
result.ToList();
}
catch
(Exception ex)
{
throw
ex;
}
}
public
List<T> QueryByFilter<T>(
string
filter,
int
pageIndex,
int
pageSize)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
QueryOptions queryOptions =
new
QueryOptions();
queryOptions.Start = pageIndex;
queryOptions.Rows = pageSize;
if
(pageSize > MaxQueryCount)
{
queryOptions.Rows = MaxQueryCount;
}
SolrQueryResults<T> result = solrOperation.Query(filter, queryOptions);
return
result.ToList();
}
catch
(Exception ex)
{
throw
ex;
}
}
public
List<T> QueryByFilter<T>(ISolrQuery solrQuery,
int
pageIndex,
int
pageSize)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
QueryOptions queryOptions =
new
QueryOptions();
queryOptions.Start = pageIndex;
queryOptions.Rows = pageSize;
if
(pageSize > MaxQueryCount)
{
queryOptions.Rows = MaxQueryCount;
}
SolrQueryResults<T> result = solrOperation.Query(solrQuery, queryOptions);
return
result.ToList();
}
catch
(Exception ex)
{
throw
ex;
}
}
#endregion
#region add
public
int
AddEntity<T>(T entity)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
solrOperation.Add(entity);
solrOperation.Commit();
return
1;
}
catch
(Exception ex)
{
throw
ex;
}
}
public
int
AddEntityList<T>(List<T> entityList)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
solrOperation.AddRange(entityList);
solrOperation.Commit();
return
1;
}
catch
(Exception ex)
{
throw
ex;
}
}
#endregion
#region delete
public
int
DeleteByEntity<T>(T entity)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
solrOperation.Delete(entity);
return
1;
}
catch
(Exception ex)
{
throw
ex;
}
}
public
int
DeleteByKey<T>(
string
key)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
solrOperation.Delete(key);
return
1;
}
catch
(Exception ex)
{
throw
ex;
}
}
public
int
DeleteByEntityList<T>(List<T> entityList)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
solrOperation.Delete(entityList);
return
1;
}
catch
(Exception ex)
{
throw
ex;
}
}
public
int
DeleteByKeyList<T>(List<
string
> keyList)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
solrOperation.Delete(keyList);
return
1;
}
catch
(Exception ex)
{
throw
ex;
}
}
public
int
DeleteByFilter<T>(ISolrQuery query)
{
try
{
ISolrOperations<T> solrOperation = GetSolrOperation<T>();
solrOperation.Delete(query);
return
1;
}
catch
(Exception ex)
{
throw
ex;
}
}
#endregion
#endregion
}
}
|
这里面主要是Solr的增删改查方法,需要说的下面的这个方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
private
static
void
RegisterSolrInstance()
{
string path = AppDomain.CurrentDomain.BaseDirectory + @
"\SolrConfig\SolrConfig.xml"
;
SolrCollection solrCollection = Deserialize<SolrCollection>(path);
Type startUpType =
typeof
(Startup);
foreach (SolrConfigs solrConfig
in
solrCollection.SolrConfigs)
{
foreach (SchemaInfo schema
in
solrConfig.Schemas)
{
MethodInfo method = startUpType.GetMethod(
"Init"
,
new
Type[] {
typeof
(string) })
.MakeGenericMethod(Type.GetType(schema.EntityType));
method.Invoke(
null
,
new
object[] { solrConfig.BaseAddress + schema.ServiceName });
}
}
}
|
就是我们第一次使用SolrHelper的时候,将配置文件中所有的Solr实例都进行注册,用的时候我们只需要通过下面的代码获取即可
1
2
3
4
|
private
ISolrOperations<T> GetSolrOperation<T>()
{
return
ServiceLocator.Current.GetInstance<ISolrOperations<T>>();
}
|
接下来看我们的SolrCollection类
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
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Xml.Serialization;
namespace
SolrCURDDemo
{
[XmlRoot(
"SolrConfigCollection"
)]
public
class
SolrCollection
{
[XmlElement(
"SolrConfigs"
)]
public
SolrConfigs[] SolrConfigs;
}
public
class
SolrConfigs
{
[XmlElement(
"Schema"
)]
public
SchemaInfo[] Schemas;
[XmlAttribute(
"baseAddress"
)]
public
string
BaseAddress;
}
public
class
SchemaInfo
{
[XmlAttribute(
"name"
)]
public
string
ServiceName;
[XmlAttribute(
"entityName"
)]
public
string
EntityType;
}
}
|
对应于我们的SolrConfig.xml文件,用于反序列化,结合SolrHelper中的Desrialize方法就能明白了。
OK,我们的窗体如下
OK,我们看一下保存代码很简单,如下
1
2
3
4
5
6
|
UserInfoEntity userInfoEntity =
new
UserInfoEntity();
userInfoEntity.UserNo = userNo;
userInfoEntity.Name = name;
userInfoEntity.Age = age;
userInfoEntity.IsMarried = isMarried;
int
suc = SolrHelper.GetInstance().AddEntity<UserInfoEntity>(userInfoEntity);
|
保存成功后,我们先在Solr中查询,结果如下
接着我们在Demo中查询,代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
string
filter =
this
.txtFilter.Text.Trim();
if
(filter ==
string
.Empty)
{
CommonMessage.ShowMessage(Resources.Msg_Input_Filter);
return
;
}
try
{
List<UserInfoEntity> userInfoList = SolrHelper.GetInstance().QueryByFilter<UserInfoEntity>(filter);
this
.dgvSearchResult.DataSource = userInfoList;
this
.BuildRowNumber();
}
catch
(Exception ex)
{
CommonMessage.ShowMessage(ex.Message);
}
|
可以查询出结果
在得到这样的结果我不得不说,我上面的SolrConfig配置文件的内容应该是这样的
1
2
3
4
5
6
7
8
9
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
SolrConfigCollection
>
<
SolrConfigs
baseAddress
=
"Http://192.168.192.128:8080/solr/MyTest."
>
<
Schema
name
=
"UserInfo"
entityName
=
"SolrCURDDemo.UserInfoEntity"
></
Schema
>
</
SolrConfigs
>
<!--<SolrConfigs baseAddress="Http://192.168.192.128:8080/solr/MyOtherTest.">
<Schema name="UserInfo"></Schema>
</SolrConfigs>-->
</
SolrConfigCollection
>
|
但是不知道怎么回事,我想改上面的地址,因为我少了/solr。但是51cto这个编辑器在chrome和IE9下没办法修改,甚至是我想整个删除都不行,郁闷了,再给大家贴一次。
我们再看看删除的代码
1
2
3
4
5
6
7
|
string
userNo = txtUserNo.Text.Trim();
if
(userNo ==
string
.Empty)
{
CommonMessage.ShowMessage(Resources.Msg_InputUserNo);
return
;
}
int
suc = SolrHelper.GetInstance().DeleteByKey<UserInfoEntity>(userNo);
|
OK,这个删除是根据主键删除,还有根据实体删除,查询条件删除。看看SolrHelper类中的方法你就清楚了。在这里给大家推荐几个网站
http://en.wikipedia.org/wiki/Apache_Solr
大家去学吧!
最后我想说的是大家下载solrNet的时候不要去官网下载,不知道怎么回事,官网的SolrNet-0.4.0.xx版本有问题,提交保存数据之后会报400错误,但是数据能保存进去,需要重启tomcat才能看到。所以建议大家去GitHub下载。GitHub链接地址:https://github.com/mausch/SolrNet。
官网地址:http://code.google.com/p/solrnet/
本文转自 BruceAndLee 51CTO博客,原文链接:http://blog.51cto.com/leelei/1227895,如需转载请自行联系原作者