展现在我们眼前的solr是: 一个war包 + 各种jar包 + 配置
1、Define a the schema tells Solr about the contents of documents it will be indexing.定义schema.xml。
2、Deploy Solr to your application server.布署solr服务
3、Feed Solr the document for which your users will search. 建索引
4、Expose search functionality in your application. 查询
注:服务的形式有三种Embedded(直接调用,无传输问题,不能对外服务)、standalone、cluster。
以上指的是standalone的形式。
positionIncrementGap的作用:对multivalue里头多个值域进行搜索时。多个value之间我认为应该是保持相互独立的,但是在实际搜索中感觉solr把所有的值域都串在一起,当作一个长value来处理,没有达到我想要的效果。例子: Suppose a document has a multi-valued "author" field. Like this:
author: John Doe author: Bob Smith
With a position increment gap of 0, a phrase query of "doe bob" would be a match. But often it is undesirable for that kind of match across different field values. A position increment gap controls the virtual space between the last token of one field instance and the first token of the next instance. With a gap of 100, this prevents phrase queries (even with a modest slop factor) from matching across instances.
<!-- A text field that only splits on whitespace for exact matching of words -->
<fieldType name="text_ws"class="solr.TextField"positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
</analyzer>
</fieldType>
<!-- A general text field that has reasonable, generic cross-language defaults: it tokenizes with StandardTokenizer, removes stop words from case-insensitive "stopwords.txt" (empty by default), and down cases. At query time only, it also applies synonyms. -->
<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" />
<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>
2.2 solrconfig.xml
² request handlers
² listeners (processes that "listen" for particular query-related events; listeners can be used to trigger the execution of special code, such as invoking some common queries to warm-up caches)
² the Request Dispatcher for managing HTTP communications
² the Admin Web interface
² parameters related to replication and duplication
3、 Data Import Handler
我们不采用。1、与solr的耦合太强,2、不支持mongodb等其他数据源,3、不适用于复杂数据源的情况,例如Mysql与Mongodb的组合。
4、 Solrj
4.1 solrj Index
我们利用solrj编写index服务,不用DataImportHandler. privatefinalstatic String URL = "http://localhost:8983/solr"; private HttpSolrServer server = null;
@Before publicvoid init() {
server = new HttpSolrServer(URL);
} publicvoid index() { try {
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id","1");
doc.addField("msg_title", "这是我的第一个solrj的程序");
doc.addField("msg_content","我的solrj的程序究竟能不能跑得起来呢?");
Date date = new Date();
doc.addField("tdate_field",date);
doc.addField("date_field",date);
server.add(doc);
server.commit();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
<requestHandler name="/replication"class="solr.ReplicationHandler" >
<lst name="master">
<str name="enable">${enable.master:false}</str>
<str name="replicateAfter">commit</str>
<str name="replicateAfter">startup</str> <!--<str name="backupAfter">optimise</str>--> <!--If configuration files need to be replicated give the names here, separated by comma -->
<str name="confFiles">${CONF_FILES}</str> <!--The default value of reservation is 10 secs.See the documentation below . Normally , you should not need to specify this -->
<str name="commitReserveDuration">00:00:10</str>
</lst>
<lst name="slave">
<str name="enable">${enable.slave:false}</str>
<str name="masterUrl">${MASTER_CORE_URL}</str>
<str name="pollInterval">${POLL_TIME}</str>
</lst>
</requestHandler>
How does it work? 工作原理
该功能是依赖于Lucene的IndexDeletionPolicy特性实现的。通过该API,Lucene暴露了IndexCommits作为每次 commit/optimize的回调。 一次IndexCommit 调用暴露了每次commit相关的文件。这便使得我们得以确认哪些文件是需要被复制的。
按照solr传统,所有的操作都是通过Restful API完成的。
How does the slave replicate?slave如何复制
Master是无法感知slaves的,salve会持续轮循master(依据'pollInterval参数')检测当前mater的索引版本。如果slave发现master上有更新版本的索引,便发起repliaction过程。
· Slave发起filelis命令,获得文件列表。该命令返回文件名的同时还会返回metadate(size,lastmodifyed,alias)。
· Slave会检查本地的索引。接着会下载缺少的文件(命令名为“filecontent”)。这会使用一种定制的格式(类似HTTP chunked encoding)每个文件的全部或部份内容。如果连接断开,下载会在上一次失败的点继续。在任意点,会尝式5次,如果都失败,就会放弃整个replication.
· 文件会被下载至一个临时文件夹。所以如果slave或者master在replication过程中宕机了,不会造成任何损失,只是停止了当前的replication。
· 当下载完成后,所有的新文件被移至slave的活动索引目录,而且文件的时间戳会与master上的一致。
· Slave的 ReplicationHandler 会发起‘commit’命令,新的索引被加载。
How are configuration files replicated?配置文件如何被复制
· 需要复制的文件被必须被'confFiles'参数显式指明。
· 只有conf文件夹下的solr实例会被复制。
· 配置文件只会跟随索引被复制。意味着即使master的一个文件被改变了,只有等到master上一次新的commit/optimize,这些文件才会被复制。
· 不同于索引文件,配置文件没有时间戳可用,它们会通过校验和被比较。如果 master和slave上的schema.xml的校验和相同,则会被视为相同文件。
· 配置文件也会在被移至目的文件夹前,被先下载到临时文件,老文件会被重命令,ReplicationHandler 不会自动清理配置文件。
· 如果replication包含了最新版本的conf文件,对应的solr核会被重新加载,而不是发起一条"commit"命令