数据搜索
Moqui框架中的数据搜索特性是基于ElasticSearch的。它是一个基于 Apache Lucene的分布式文本搜索工具。ElasticSearch使用JSON文档作为搜索内容,JSON文档中的每个命名字段是一个搜索的方面(facet)。数据文档特性生成文档时有4个ElasticSearch使用的特殊的字段,在数据文档章节中描述的:(_index, _type, _id 和 _timestamp)。
数据搜索有两个要点:索引 和 搜索。框架中处理索引的服务是 org.moqui.search.SearchServices.index#DataFeedDocuments。此服务实现了 org.moqui.EntityServices.receive#DataFeed 接口并接受接口的所有参数,但是只使用 documentList 参数,它是用ElasticSearch索引的数据文档列表。
它也有另一个参数,getOriginalDocuments ,当设置为true时,服务将填充并返回 originalDocumentList,来自ElasticSearch的匹配文档的索引前版本的列表。服务总是返回一个有索引完成后原始列表中的每个文档的版本号列表的documentVersionList参数,以显示每个文档在索引中被更新了多少次。
之前章节中的例子使用了一个应用特定的服务来获取推送的数据Feed,这有一个使用框架中的索引服务的推送数据Feed配置的示例:
<xml>
<moqui.entity.feed.DataFeed dataFeedId="PopCommerceSearch" dataFeedTypeEnumId="DTFDTP_RT_PUSH" feedName="PopCommerce Search"
feedReceiveServiceName="org.moqui.search.SearchServices.index#DataFeedDocuments"/>
<moqui.entity.feed.DataFeedDocument dataFeedId="PopCommerceSearch" dataDocumentId="PopcProduct"/>
</xml>
你也可以直接使用 ElasticSearch API来索文档,EntityFacade产生的数据文档或者你想搜索的任意JSON文档都可以。更完整的信息请查看ElasticSearch文档。这时一个索引有_index, _type, _id条目集的嵌套Map形式的JSON文件的例子:
IndexResponse response = ec.elasticSearchClient.prepareIndex(document._index, document._type, document._id).setSource(document).execute().actionGet()
要使用 org.moqui.search.SearchServices.search#DataDocuments 服务来搜索数据文档,像这样:
<service-call name="org.moqui.search.SearchServices.search#DataDocuments" out-map="context" in-map="context + [indexName:’popc’]"/>
注意在此例中,queryString, pageIndex和pageSize参数来自搜索表单并从请求参数中填入上下文。此服务的参数有:
- queryString: 将被传到Lucene classic查询解析器的搜索查询字符串,相见 文档
- documentType: ElasticSearch文档类型,与文档中的_type字段和DataDocument.dataDocumentId匹配;前面章节的例子包括PopProduct和HmProject。
- PageIndex, pageSize: Moqui的XML列表表单的标准分页参数,有它们服务会被使用得很容易;结果中只有从 pageIndex*pageSize开始的pageSize结果将会返回
- flattenDocument: 默认为 false。如果设置为true,嵌套的Map结果(对象表单、JSON文档的文本表单)形式的每个文档将被摊平到单个Map,键/值对取自所有的嵌套的Map和Map列表;如果一样的Map条目键发现不止一次,文档中后面的值将会覆盖前面的值(请查看Stupidtilities.flattenNestedMap()方法)
此服务返回一个documentList参数,它是一个Map列表,每个Map表示一份数据文档。它也返回多个documentList*参数,它们是Moqui的XML列表表单分页模式(Count, PageIndex, PageSize, PageMaxIndex, PageRangeLow, and PageRangeHigh)的一部分。这些别用在显然一个列表表单时,也能被用于其他目标,也一样有用。
除了使用此服务外,你也能直接通过ElasticSearch API来获取结果。注意有两个主要步骤:搜索以拿回每个文档的3个标识字段,然后一个 multi-go 来获取文档的所有内容。在这个例子中,获取每个文档作为一个Map(getSourceAsMap()方法),ElasticSearch API也支持获取每个文档为JSON文档(getSourceAsString()方法)。
SearchHits hits =
ec.elasticSearchClient.prepareSearch().setIndices(indexName).setTypes(documentType).setQuery(QueryBuilders.queryString(queryString)).setFrom(fromOffset).setSize(sizeLimit).execute().actionGet().getHits()
if (hits.getTotalHits() > 0) {
MultiGetRequestBuilder mgrb = ec.elasticSearchClient.prepareMultiGet()
for (SearchHit hit in hits)
mgrb.add(hit.getIndex(), hit.getType(), hit.getId())
Iterator mgirIt = mgrb.execute().actionGet().iterator()
while(mgirIt.hasNext()) {
MultiGetItemResponse mgir = mgirIt.next()
Map document = mgir.getResponse().getSourceAsMap()
documentList.add(document)
}
}
除了索引和搜索外,ElasticSearch的另一个要了解的方面是部署选项。默认Moqui框架为了快速、方便地访问,有一个ElasticSearch的内嵌节点运行在同一个JVM中。也可以使用远程的ElasticSearch服务器。
最容易的分布式部署模式是每个Moqui应用服务是ElasticSearch集群中的一个节点,如果你有分离的ES节点有存储实际的搜索数据,那么设置应用服务器ES节点不要保存任何数据。用这种方法,结果将在应用服务器上聚集,但是实际的根据索引数据的搜索将在集群种的其他服务器上完成。