设为首页 收藏本站
查看: 859|回复: 0

[经验分享] 全文检索引擎及工具 Lucene Solr

[复制链接]

尚未签到

发表于 2017-12-19 09:22:22 | 显示全部楼层 |阅读模式
  import org.slf4j.LoggerFactory
  import com.typesafe.config.{ConfigFactory, _}
  import org.apache.lucene
  import lucene.index.{DirectoryReader, IndexWriter, IndexWriterConfig, _}
  import lucene.document.{Field, FieldType, _}
  import lucene.analysis.{CharArraySet, _}
  import lucene.search.{IndexSearcher, _}
  import lucene.store.{RAMDirectory, _}
  import lucene.analysis.cn.smart.{SmartChineseAnalyzer, _}
  import org.apache.lucene.index.IndexWriterConfig.OpenMode
  import org.apache.lucene.queryparser.classic.QueryParser
  import scala.collection.convert.ImplicitConversions._
  import scala.io.Source
  import scala.util.{Failure, Success, Try}
  val log = LoggerFactory.getLogger(this.getClass)
  val conf = ConfigFactory.load("app")  // 读取文件配置,对Java程序员来说相当于读 app.properties配置文件

  log.info("creating lucene index for wikipedia>  // 保存lucene索引文件的目录,例如/path/to/index/
  val indexDir = conf.getString("lucene.indexDir")
  log.debug(s"lucene index writing direcotry: $indexDir")
  import org.apache.lucene
  // 创建Directory对象,或创建写入硬盘的(FSDirectory)或直接在内存中操作的(RAMDirectory)。前者需要提供一个写入索引的目录参数。

  //    val>  //小示例,直接在内存中操作算了

  val>  val stopWordsFiles = conf.getString("lucene.stopWordsFiles")
  log.debug(s"lucene.stopWordsFiles: $stopWordsFiles")
  // “停用词”表,以过滤分词结果中没啥用处的停用词
  val stopWords = stopWordsFiles.split(",").flatMap(f => Try {
  if (f.trim.nonEmpty)
  Source.fromFile(f).getLines()
  else
  Iterator.empty
  } match {
  case Success(x) => x
  case Failure(e) =>
  log.warn(s"error in loading stop words file: $f", e)
  Iterator.empty
  }).toList

  log.debug(s"stop words>  val smartcn = new SmartChineseAnalyzer(new CharArraySet(stopWords, true))
  val iwConf = new IndexWriterConfig(smartcn)
  // iwConf.setOpenMode(OpenMode.CREATE) // RAM中操作“重新创建”、“追加”几种写入模式都无所谓了
  val indexWriter = new IndexWriter(idxDir, iwConf)
  // $lucene.wikiIdTitle表示文档集合文件的路径,示例中该文件内容如下
  /*
  1832186 义胆雄心
  5376724 龙山洞
  5420049 地下情人
  5431949 里弗顿
  5455483 长隆
  5463308 阿尔伯特桥
  5470979 冈田
  5511092 肖迪奇站
  5544906 莫农加希拉_(消歧义)
  5553846 蓬莱洞
  5553849 南山洞
  5566592 开水
  5566629 氧化锑
  */
  val pgIdTtls=Source.fromFile(conf.getString("lucene.wikiIdTitle"))
  .getLines()
  .filter(ln => ln.nonEmpty)
  .map(ln => {

  val>
  (idTtl(0),>  })
  //pgIdTtls变量是一个二元组,对于Java程序员,不必了解什么是二元组,可想象成两列,第一列是唯一id,第二列是文本
  pgIdTtls.foreach(e => {
  import lucene.document._
  //创建一个Document
  val ldoc = new lucene.document.Document()
  //由于第一列是文档唯一id,不需要被索引,但需要被保存,以便在检索到结果之后能“看到”这个id字段,不保存(.setStored(false))则即使被添加到document对象,在结果中也看不到该字段
  val pageIdFieldType = new FieldType()
  pageIdFieldType.setStored(true)  // 要保存,因为我们想在结果中得到这个值
  pageIdFieldType.setIndexOptions(lucene.index.IndexOptions.NONE)  //别在id字段上做索引
  // 事实上,为了性能,可以把pageIdFieldType移到循环外,示例中放在这里是为了让FieldType的出现看起来更合理
  // 为文档创建字段,名为pageId(字段名随意取,不过在检索结果中提取时你得记得这个字段的名字),值为第一列(即文档唯一编号)
  val piFld = new lucene.document.Field("pageId", e._1, pageIdFieldType)
  ldoc.add(piFld)
  //把文档的文本内容添加到title字段,要保存(Field.Store.YES)
  ldoc.add(new lucene.document.TextField("title", e._2, Field.Store.YES))
  indexWriter.addDocument(ldoc)  // 写入index
  })
  //indexWriter.close()  // 如果用硬盘写入(FSDirectory.open方式),要记得关闭
  val searcher = new IndexSearcher(DirectoryReader.open(indexWriter))
  // 如果是读取某个目录下的index,则应该用
  // val searcher = new IndexSearcher(DirectoryReader.open(FSDirectory.open(java.nio.file.Paths.get("/path/to/index/"))))
  import lucene.queryparser.classic._
  // 在title字段上搜索
  val queryParser = new QueryParser("title", smartcn)
  // 搜索“南山洞”
  val query = queryParser.parse("南山洞")
  //
  val hitPageIdTitles = searcher
  .search(query, 30)  // 最多返回30个结果,还有更多我也不想要了(类似SQL的limit 30
  .scoreDocs.map(searcher doc _.doc)
  .map(d => (d.get("pageId"), d.get("title")))
  //上一scala语句对java程序员来说理解起来可能稍微有点费力,翻译为java,是这样的
  /*
  ScoreDoc[] scoreDocs=searcher.search(query,30).scoreDocs;
  for (ScoreDoc scoreDoc : scoreDocs) {
  //得到检索到的Document
  org.apache.lucene.document.Document d= searcher.doc(scoreDoc.doc);
  // 从Document中获取文档编号和文本内容
  System.out.println(d.get("pageId")+", "+d.get("title"))
  }
  */
  //检索到两个结果(5553849,南山洞), (5376724,龙山洞)

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-425601-1-1.html 上篇帖子: solr基础使用概述 下篇帖子: 11.solr学习速成之MoreLikeThis
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表