如何使用Apache Pig与Lucene集成,还不知道的道友们,可以先看下上篇,熟悉下具体的流程。
在与Lucene集成过程中,我们发现最终还要把生成的Lucene索引,拷贝至本地磁盘,才能提供检索服务,这样以来,比较繁琐,而且有以下几个缺点:
(一)在生成索引以及最终能提供正常的服务之前,索引经过多次落地操作,这无疑会给磁盘和网络IO,带来巨大影响
(二)Lucene的Field的配置与其UDF函数的代码耦合性过强,而且提供的配置也比较简单,不太容易满足,灵活多变的检索需求和服务,如果改动索引配置,则有可能需要重新编译源码。
(三)对Hadoop的分布式存储系统HDFS依赖过强,如果使用与Lucene集成,那么则意味着你提供检索的Web服务器,则必须跟hadoop的存储节点在一个机器上,否则,无法从HDFS上下拉索引,除非你自己写程序,或使用scp再次从目标机传输,这样无疑又增加了,系统的复杂性。
鉴于有以上几个缺点,所以建议大家使用Solr或ElasticSearch这样的封装了Lucene更高级的API框架,那么Solr与ElasticSearch和Lucene相比,又有什么优点呢?
(1)在最终的写入数据时,我们可以直接最终结果写入solr或es,同时也可以在HDFS上保存一份,作为灾备。
(2)使用了solr或es,这时,我们字段的配置完全与UDF函数代码无关,我们的任何字段配置的变动,都不会影响Pig的UDF函数的代码,而在UDF函数里,唯一要做的,就是将最终数据,提供给solr和es服务。
(3)solr和es都提供了restful风格的http操作方式,这时候,我们的检索集群完全可以与Hadoop集群分离,从而让他们各自都专注自己的服务。
下面,散仙就具体说下如何使用Pig和Solr集成?
(1)依旧访问这个地址下载源码压缩包。
(2)提取出自己想要的部分,在eclipse工程中,修改定制适合自己环境的的代码(Solr版本是否兼容?hadoop版本是否兼容?,Pig版本是否兼容?)。
(3)使用ant重新打包成jar
(4)在pig里,注册相关依赖的jar包,并使用索引存储
注意,在github下载的压缩里直接提供了对SolrCloud模式的提供,而没有提供,普通模式的函数,散仙在这里稍作修改后,可以支持普通模式的Solr服务,代码如下:
SolrOutputFormat函数
- package com.pig.support.solr;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.concurrent.Executors;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
- import org.apache.hadoop.io.Writable;
- import org.apache.hadoop.mapreduce.JobContext;
- import org.apache.hadoop.mapreduce.OutputCommitter;
- import org.apache.hadoop.mapreduce.RecordWriter;
- import org.apache.hadoop.mapreduce.TaskAttemptContext;
- import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
- import org.apache.solr.client.solrj.SolrServer;
- import org.apache.solr.client.solrj.SolrServerException;
- import org.apache.solr.client.solrj.impl.CloudSolrServer;
- import org.apache.solr.client.solrj.impl.HttpSolrServer;
- import org.apache.solr.common.SolrInputDocument;
- /**
- * @author qindongliang
- * 支持SOlr的SolrOutputFormat
- * 如果你想了解,或学习更多这方面的
- * 知识,请加入我们的群:
- *
- * 搜索技术交流群(2000人):324714439
- * 大数据技术1号交流群(2000人):376932160 (已满)
- * 大数据技术2号交流群(2000人):415886155
- * 微信公众号:我是攻城师(woshigcs)
- *
- * */
- public class SolrOutputFormat extends
- FileOutputFormat<Writable, SolrInputDocument> {
- final String address;
- final String collection;
- public SolrOutputFormat(String address, String collection) {
- this.address = address;
- this.collection = collection;
- }
- @Override
- public RecordWriter<Writable, SolrInputDocument> getRecordWriter(
- TaskAttemptContext ctx) throws IOException, InterruptedException {
- return new SolrRecordWriter(ctx, address, collection);
- }
- @Override
- public synchronized OutputCommitter getOutputCommitter(
- TaskAttemptContext arg0) throws IOException {
- return new OutputCommitter(){
- @Override
- public void abortTask(TaskAttemptContext ctx) throws IOException {
- }
- @Override
- public void commitTask(TaskAttemptContext ctx) throws IOException {
- }
- @Override
- public boolean needsTaskCommit(TaskAttemptContext arg0)
- throws IOException {
- return true;
- }
- @Override
- public void setupJob(JobContext ctx) throws IOException {
- }
- @Override
- public void setupTask(TaskAttemptContext ctx) throws IOException {
- }
- };
- }
- /**
- * Write out the LuceneIndex to a local temporary location.<br/>
- * On commit/close the index is copied to the hdfs output directory.<br/>
- *
- */
- static class SolrRecordWriter extends RecordWriter<Writable, SolrInputDocument> {
- /**Solr的地址*/
- SolrServer server;
- /**批处理提交的数量**/
- int batch = 5000;
- TaskAttemptContext ctx;
- List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>(batch);
- ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
- /**
- * Opens and forces connect to CloudSolrServer
- *
- * @param address
- */
- public SolrRecordWriter(final TaskAttemptContext ctx, String address, String collection) {
- try {
- this.ctx = ctx;
- server = new HttpSolrServer(address);
- exec.scheduleWithFixedDelay(new Runnable(){
- public void run(){
- ctx.progress();
- }
- }, 1000, 1000, TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- RuntimeException exc = new RuntimeException(e.toString(), e);
- exc.setStackTrace(e.getStackTrace());
- throw exc;
- }
- }
- /**
- * On close we commit
- */
- @Override
- public void close(final TaskAttemptContext ctx) throws IOException,
- InterruptedException {
- try {
- if (docs.size() > 0) {
- server.add(docs);
- docs.clear();
- }
- server.commit();
- } catch (SolrServerException e) {
- RuntimeException exc = new RuntimeException(e.toString(), e);
- exc.setStackTrace(e.getStackTrace());
- throw exc;
- } finally {
- server.shutdown();
- exec.shutdownNow();
- }
- }
- /**
- * We add the indexed documents without commit
- */
- @Override
- public void write(Writable key, SolrInputDocument doc)
- throws IOException, InterruptedException {
- try {
- docs.add(doc);
- if (docs.size() >= batch) {
- server.add(docs);
- docs.clear();
- }
- } catch (SolrServerException e) {
- RuntimeException exc = new RuntimeException(e.toString(), e);
- exc.setStackTrace(e.getStackTrace());
- throw exc;
- }
- }
- }
- }
package com.pig.support.solr; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.apache.hadoop.io.Writable; import org.apache.hadoop.mapreduce.JobContext; import org.apache.hadoop.mapreduce.OutputCommitter; import org.apache.hadoop.mapreduce.RecordWriter; import org.apache.hadoop.mapreduce.TaskAttemptContext; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CloudSolrServer; import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.apache.solr.common.SolrInputDocument; /** * @author qindongliang * 支持SOlr的SolrOutputFormat * 如果你想了解,或学习更多这方面的 * 知识,请加入我们的群: * * 搜索技术交流群(2000人):324714439 * 大数据技术1号交流群(2000人):376932160 (已满) * 大数据技术2号交流群(2000人):415886155 * 微信公众号:我是攻城师(woshigcs) * * */ public class SolrOutputFormat extends FileOutputFormat<Writable, SolrInputDocument> { final String address; final String collection; public SolrOutputFormat(String address, String collection) { this.address = address; this.collection = collection; } @Override public RecordWriter<Writable, SolrInputDocument> getRecordWriter( TaskAttemptContext ctx) throws IOException, InterruptedException { return new SolrRecordWriter(ctx, address, collection); } @Override public synchronized OutputCommitter getOutputCommitter( TaskAttemptContext arg0) throws IOException { return new OutputCommitter(){ @Override public void abortTask(TaskAttemptContext ctx) throws IOException { } @Override public void commitTask(TaskAttemptContext ctx) throws IOException { } @Override public boolean needsTaskCommit(TaskAttemptContext arg0) throws IOException { return true; } @Override public void setupJob(JobContext ctx) throws IOException { } @Override public void setupTask(TaskAttemptContext ctx) throws IOException { } }; } /** * Write out the LuceneIndex to a local temporary location.<br/> * On commit/close the index is copied to the hdfs output directory.<br/> * */ static class SolrRecordWriter extends RecordWriter<Writable, SolrInputDocument> { /**Solr的地址*/ SolrServer server; /**批处理提交的数量**/ int batch = 5000; TaskAttemptContext ctx; List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>(batch); ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); /** * Opens and forces connect to CloudSolrServer * * @param address */ public SolrRecordWriter(final TaskAttemptContext ctx, String address, String collection) { try { this.ctx = ctx; server = new HttpSolrServer(address); exec.scheduleWithFixedDelay(new Runnable(){ public void run(){ ctx.progress(); } }, 1000, 1000, TimeUnit.MILLISECONDS); } catch (Exception e) { RuntimeException exc = new RuntimeException(e.toString(), e); exc.setStackTrace(e.getStackTrace()); throw exc; } } /** * On close we commit */ @Override public void close(final TaskAttemptContext ctx) throws IOException, InterruptedException { try { if (docs.size() > 0) { server.add(docs); docs.clear(); } server.commit(); } catch (SolrServerException e) { RuntimeException exc = new RuntimeException(e.toString(), e); exc.setStackTrace(e.getStackTrace()); throw exc; } finally { server.shutdown(); exec.shutdownNow(); } } /** * We add the indexed documents without commit */ @Override public void write(Writable key, SolrInputDocument doc) throws IOException, InterruptedException { try { docs.add(doc); if (docs.size() >= batch) { server.add(docs); docs.clear(); } } catch (SolrServerException e) { RuntimeException exc = new RuntimeException(e.toString(), e); exc.setStackTrace(e.getStackTrace()); throw exc; } } } }
SolrStore函数
- package com.pig.support.solr;
- import java.io.IOException;
- import java.util.Properties;
- import org.apache.hadoop.fs.Path;
- import org.apache.hadoop.io.Writable;
- import org.apache.hadoop.mapreduce.Job;
- import org.apache.hadoop.mapreduce.OutputFormat;
- import org.apache.hadoop.mapreduce.RecordWriter;
- import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
- import org.apache.pig.ResourceSchema;
- import org.apache.pig.ResourceSchema.ResourceFieldSchema;
- import org.apache.pig.ResourceStatistics;
- import org.apache.pig.StoreFunc;
- import org.apache.pig.StoreMetadata;
- import org.apache.pig.data.Tuple;
- import org.apache.pig.impl.util.UDFContext;
- import org.apache.pig.impl.util.Utils;
- import org.apache.solr.common.SolrInputDocument;
- /**
- *
- * Create a lucene index
- *
- */
- public class SolrStore extends StoreFunc implements StoreMetadata {
- private static final String SCHEMA_SIGNATURE = "solr.output.schema";
- ResourceSchema schema;
- String udfSignature;
- RecordWriter<Writable, SolrInputDocument> writer;
- String address;
- String collection;
- public SolrStore(String address, String collection) {
- this.address = address;
- this.collection = collection;
- }
- public void storeStatistics(ResourceStatistics stats, String location,
- Job job) throws IOException {
- }
- public void storeSchema(ResourceSchema schema, String location, Job job)
- throws IOException {
- }
- @Override
- public void checkSchema(ResourceSchema s) throws IOException {
- UDFContext udfc = UDFContext.getUDFContext();
- Properties p = udfc.getUDFProperties(this.getClass(),
- new String[] { udfSignature });
- p.setProperty(SCHEMA_SIGNATURE, s.toString());
- }
- public OutputFormat<Writable, SolrInputDocument> getOutputFormat()
- throws IOException {
- // not be used
- return new SolrOutputFormat(address, collection);
- }
- /**
- * Not used
- */
- @Override
- public void setStoreLocation(String location, Job job) throws IOException {
- FileOutputFormat.setOutputPath(job, new Path(location));
- }
- @Override
- public void setStoreFuncUDFContextSignature(String signature) {
- this.udfSignature = signature;
- }
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @Override
- public void prepareToWrite(RecordWriter writer) throws IOException {
- this.writer = writer;
- UDFContext udc = UDFContext.getUDFContext();
- String schemaStr = udc.getUDFProperties(this.getClass(),
- new String[] { udfSignature }).getProperty(SCHEMA_SIGNATURE);
- if (schemaStr == null) {
- throw new RuntimeException("Could not find udf signature");
- }
- schema = new ResourceSchema(Utils.getSchemaFromString(schemaStr));
- }
- /**
- * Shamelessly copied from : https://issues.apache.org/jira/secure/attachment/12484764/NUTCH-1016-2.0.patch
- * @param input
- * @return
- */
- private static String stripNonCharCodepoints(String input) {
- StringBuilder retval = new StringBuilder(input.length());
- char ch;
- for (int i = 0; i < input.length(); i++) {
- ch = input.charAt(i);
- // Strip all non-characters
- // http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:Noncharacter_Code_Point=True:]
- // and non-printable control characters except tabulator, new line
- // and carriage return
- if (ch % 0x10000 != 0xffff && // 0xffff - 0x10ffff range step
- // 0x10000
- ch % 0x10000 != 0xfffe && // 0xfffe - 0x10fffe range
- (ch <= 0xfdd0 || ch >= 0xfdef) && // 0xfdd0 - 0xfdef
- (ch > 0x1F || ch == 0x9 || ch == 0xa || ch == 0xd)) {
- retval.append(ch);
- }
- }
- return retval.toString();
- }
- @Override
- public void putNext(Tuple t) throws IOException {
- final SolrInputDocument doc = new SolrInputDocument();
- final ResourceFieldSchema[] fields = schema.getFields();
- int docfields = 0;
- for (int i = 0; i < fields.length; i++) {
- final Object value = t.get(i);
- if (value != null) {
- docfields++;
- doc.addField(fields[i].getName().trim(), stripNonCharCodepoints(value.toString()));
- }
- }
- try {
- if (docfields > 0)
- writer.write(null, doc);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return;
- }
- }
- }
package com.pig.support.solr; import java.io.IOException; import java.util.Properties; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.Writable; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.OutputFormat; import org.apache.hadoop.mapreduce.RecordWriter; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.pig.ResourceSchema; import org.apache.pig.ResourceSchema.ResourceFieldSchema; import org.apache.pig.ResourceStatistics; import org.apache.pig.StoreFunc; import org.apache.pig.StoreMetadata; import org.apache.pig.data.Tuple; import org.apache.pig.impl.util.UDFContext; import org.apache.pig.impl.util.Utils; import org.apache.solr.common.SolrInputDocument; /** * * Create a lucene index * */ public class SolrStore extends StoreFunc implements StoreMetadata { private static final String SCHEMA_SIGNATURE = "solr.output.schema"; ResourceSchema schema; String udfSignature; RecordWriter<Writable, SolrInputDocument> writer; String address; String collection; public SolrStore(String address, String collection) { this.address = address; this.collection = collection; } public void storeStatistics(ResourceStatistics stats, String location, Job job) throws IOException { } public void storeSchema(ResourceSchema schema, String location, Job job) throws IOException { } @Override public void checkSchema(ResourceSchema s) throws IOException { UDFContext udfc = UDFContext.getUDFContext(); Properties p = udfc.getUDFProperties(this.getClass(), new String[] { udfSignature }); p.setProperty(SCHEMA_SIGNATURE, s.toString()); } public OutputFormat<Writable, SolrInputDocument> getOutputFormat() throws IOException { // not be used return new SolrOutputFormat(address, collection); } /** * Not used */ @Override public void setStoreLocation(String location, Job job) throws IOException { FileOutputFormat.setOutputPath(job, new Path(location)); } @Override public void setStoreFuncUDFContextSignature(String signature) { this.udfSignature = signature; } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void prepareToWrite(RecordWriter writer) throws IOException { this.writer = writer; UDFContext udc = UDFContext.getUDFContext(); String schemaStr = udc.getUDFProperties(this.getClass(), new String[] { udfSignature }).getProperty(SCHEMA_SIGNATURE); if (schemaStr == null) { throw new RuntimeException("Could not find udf signature"); } schema = new ResourceSchema(Utils.getSchemaFromString(schemaStr)); } /** * Shamelessly copied from : https://issues.apache.org/jira/secure/attachment/12484764/NUTCH-1016-2.0.patch * @param input * @return */ private static String stripNonCharCodepoints(String input) { StringBuilder retval = new StringBuilder(input.length()); char ch; for (int i = 0; i < input.length(); i++) { ch = input.charAt(i); // Strip all non-characters // http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:Noncharacter_Code_Point=True:] // and non-printable control characters except tabulator, new line // and carriage return if (ch % 0x10000 != 0xffff && // 0xffff - 0x10ffff range step // 0x10000 ch % 0x10000 != 0xfffe && // 0xfffe - 0x10fffe range (ch <= 0xfdd0 || ch >= 0xfdef) && // 0xfdd0 - 0xfdef (ch > 0x1F || ch == 0x9 || ch == 0xa || ch == 0xd)) { retval.append(ch); } } return retval.toString(); } @Override public void putNext(Tuple t) throws IOException { final SolrInputDocument doc = new SolrInputDocument(); final ResourceFieldSchema[] fields = schema.getFields(); int docfields = 0; for (int i = 0; i < fields.length; i++) { final Object value = t.get(i); if (value != null) { docfields++; doc.addField(fields[i].getName().trim(), stripNonCharCodepoints(value.toString())); } } try { if (docfields > 0) writer.write(null, doc); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } }
Pig脚本如下:
- --注册依赖文件的jar包
- REGISTER ./dependfiles/tools.jar;
- --注册solr相关的jar包
- REGISTER ./solrdependfiles/pigudf.jar;
- REGISTER ./solrdependfiles/solr-core-4.10.2.jar;
- REGISTER ./solrdependfiles/solr-solrj-4.10.2.jar;
- REGISTER ./solrdependfiles/httpclient-4.3.1.jar
- REGISTER ./solrdependfiles/httpcore-4.3.jar
- REGISTER ./solrdependfiles/httpmime-4.3.1.jar
- REGISTER ./solrdependfiles/noggit-0.5.jar
- --加载HDFS数据,并定义scheaml
- a = load '/tmp/data' using PigStorage(',') as (sword:chararray,scount:int);
- --存储到solr中,并提供solr的ip地址和端口号
- store d into '/user/search/solrindextemp' using com.pig.support.solr.SolrStore('http://localhost:8983/solr/collection1','collection1');
- ~
- ~
- ~
--注册依赖文件的jar包 REGISTER ./dependfiles/tools.jar; --注册solr相关的jar包 REGISTER ./solrdependfiles/pigudf.jar; REGISTER ./solrdependfiles/solr-core-4.10.2.jar; REGISTER ./solrdependfiles/solr-solrj-4.10.2.jar; REGISTER ./solrdependfiles/httpclient-4.3.1.jar REGISTER ./solrdependfiles/httpcore-4.3.jar REGISTER ./solrdependfiles/httpmime-4.3.1.jar REGISTER ./solrdependfiles/noggit-0.5.jar --加载HDFS数据,并定义scheaml a = load '/tmp/data' using PigStorage(',') as (sword:chararray,scount:int); --存储到solr中,并提供solr的ip地址和端口号 store d into '/user/search/solrindextemp' using com.pig.support.solr.SolrStore('http://localhost:8983/solr/collection1','collection1'); ~ ~ ~
配置成功之后,我们就可以运行程序,加载HDFS上数据,经过计算处理之后,并将最终的结果,存储到Solr之中,截图如下:
成功之后,我们就可以很方便的在solr中进行毫秒级别的操作了,例如各种各样的全文查询,过滤,排序统计等等!
相关推荐
1.联网下载插件:使用plugin命令,例如plugin.bat -install mobz/elasticsearch-head。 2.下载解压插件:从github下载head插件的源码,解压缩到plugins/head目录下,重启ElasticSearch。 五、ElasticSearch基本操作...
- **高度封装**:Elasticsearch对Lucene进行了高度封装,并提供了RESTful API接口,降低了开发者的使用门槛。 - **集群支持**:通过分片和副本机制,Elasticsearch能够实现集群下的高性能和高可用性。 - **易于部署...
对于Elasticsearch和Lucene的竞争,由于Elasticsearch完美封装了Lucene核心库,并提供了友好的Restful-API,开发者使用时无需过多关注底层机制,直接可以开箱即用。而且,Elasticsearch的分片与副本机制也直接解决了...
### Elasticsearch与ES-RestAPI技术概述 #### 一、Elasticsearch简介 Elasticsearch是一款高性能的分布式搜索和分析引擎,适用于实时数据处理场景。它基于Lucene构建,提供了强大的分布式多用户全文检索功能,通过...
适用于Elasticsearch的Rosette分析介绍Rosette Analysis插件将Lucene分析模块集成到elasticsearch中。 这些模块封装了(Rosette)。 有关更多信息,请参阅《 Rosette语言学平台应用程序开发人员指南:Lucene / Solr...
主要是利用了Pig框架简化了自己写Hadoop MapReduce程序来构建大规模并行索引的问题,里面封装了主流的全文检索框架,如Lucene,Solr和ElasticSearch 并且支持SolrCloud集群和ElasticSearch集群的分布式索引构建。 这...
- 可以考虑使用Solr或Elasticsearch,它们是基于Lucene的企业级搜索解决方案,提供了更高级的特性,如分布式搜索、实时索引和更复杂的查询语法。 通过以上步骤,你可以创建一个基于Java和Lucene的全文搜索引擎,为...
为了应对大数据量的索引,Lucene支持多线程索引和分布式搜索,例如通过Solr或Elasticsearch这样的分布式搜索引擎平台。 在实际应用中,我们还需要考虑一些优化策略,如合理设置缓存大小、选择合适的分析器、定期...
为提高搜索效率,可以考虑引入搜索引擎技术,如Solr或Elasticsearch。 **8. 分页与排序** 为了优化用户体验,论坛通常会对帖子列表进行分页显示。使用LIMIT和OFFSET SQL语句实现分页,根据时间、热度或其他指标进行...
9. **搜索引擎集成**:为了方便用户搜索,可能集成了Solr或Elasticsearch等全文搜索引擎,提供高效的全文检索功能。 10. **容器化部署**:Docker容器化技术可能用于部署,通过Dockerfile定义运行环境,确保应用在...
6. **分布式搜索**:通过Solr或Elasticsearch这样的封装层,Lucene可以实现分布式搜索,支持大规模数据和高并发访问,适用于企业级的搜索应用。 7. **多语言支持**:Lucene内置了多种语言的分析器,包括中文、英文...
4. 集群与分布式:通过Solr或Elasticsearch搭建分布式搜索集群,提升性能和容错能力。 总的来说,Lucene提供了强大的搜索功能,通过理解和实践,我们可以构建出高效、灵活的全文搜索引擎,满足各种复杂场景的需求。...
在实际使用中,开发者通常会结合其他框架如Solr或Elasticsearch来封装和扩展Lucene的功能,提供更高级的特性,如分布式搜索、集群管理、多租户支持等。通过深入理解Lucene的概念和机制,开发者可以构建出高效、灵活...
7. **分布式搜索**:虽然3.0版本的Lucene不直接支持分布式搜索,但书中可能包含如何在单机环境下模拟多节点索引和查询的方法,这对于理解后来的Solr或Elasticsearch等分布式搜索系统非常有帮助。 8. **性能优化**:...
在IT领域,搜索引擎是至关重要的工具,特别是在大数据和信息爆炸的时代。...在实际应用中,我们还可以结合Solr或Elasticsearch这些基于Lucene的服务器端框架,进一步扩展搜索功能,如集群、分布式搜索、实时更新等。
可能还需要使用到Lucene、Solr或Elasticsearch等开源搜索引擎库。 7. **Web服务器**:项目通常会部署在Tomcat、Jetty或Apache等Web服务器上,需要了解服务器配置和部署流程。 8. **前端技术**:HTML、CSS和...
通过这种方式,`laravel-zendsearch`允许你在Laravel应用中轻松地实现基于文件系统的全文搜索功能,无需依赖外部的搜索引擎服务,如Elasticsearch或Solr。这对于小型项目或者对实时性要求不高的场景是一个非常实用的...