【问题标题】:Hybrid of fulltext and property-based search engine全文和基于属性的搜索引擎的混合
【发布时间】:2012-10-04 14:56:48
【问题描述】:

背景:

代表不同类型活动(音乐会、足球比赛、慈善募捐等)的 SQL 数据库,其中每个都包含与活动相关的数据(音乐会 - 艺术家姓名,比赛 - 主持人/观众团队)。所有这些事件都继承自一个通用表event,其中包含与所有事件相关的数据(名称、描述、位置、开始/结束日期)。 继承是使用从HibernateDoctrine 已知的每个子类的表模型来实现的。该数据库还存储artistsidnamebirth_date)和football_teamsidnamecountrycoach_name)和@9876543333@中使用的表@ 表(通过 FK)。

问题:

创建一个给定条件({name: "manchester", startDate: "01.01.2012 - 01.02.2012"}{location: "london", description: "artists +metallica -bieber"})的搜索引擎将返回所有符合条件的事件,以及来自artists/football_teams 表的结果。

这些事件的某些属性包含大量文本,应该以全文搜索的方式进行搜索。

示例:

根据以下搜索条件:

{ location: "london", startDate: "05.11.2012 - 07.11.2012" }

搜索引擎应该返回:

  1. (足球赛事)阿森纳 vs 曼联比赛,酋长球场,伦敦,06.11.2012
  2. (音乐会活动)Metallica 音乐会,Some-Fancy-Location,05.11.2012
  3. (足球队/非赛事)阿森纳,成立时间:1886 年,联赛:英超联赛
  4. (足球队/非赛事)切尔西,成立时间:1905 年,联赛:英超联赛
  5. (节日活动)伦敦万圣节,07.11.2012
  6. (舞蹈活动)Sadler's Wells 的睡美人,45 英镑,2012 年 11 月 7 日
  7. (音乐家,不是事件)尼尔·克里斯蒂安,1943 - 2012 年,摇滚歌手

如您所见,startDate(事件相关属性)仅在发生事件时才被考虑。


搜索引擎必须扫描很多表,这就是为什么我认为我应该使用专用软件(Sphinx、Lucene、...?)并为搜索创建单独的索引。


任何人都可以建议一些解决方案来构建这样的索引吗?我可以使用什么软件作为该搜索引擎的基础?


编辑:

澄清一下:这些属性都不是必需的。其中一些包含将使用精确匹配搜索的日期,其中一些包含也将使用精确匹配搜索的短文本(如位置)。但是其中一些包含很长的文本,需要以全文方式搜索。

【问题讨论】:

  • 我没有看到你在哪里进行全文搜索,你给出的例子是完全匹配的。
  • @amirouche:你说得对,我没有给你一个合适的例子。假设 musician 有一个“biography”属性,其中包含大量文本。现在,对于以下条件:{ phrase: "+royal musician", location: "london" } 它应该返回位于伦敦的结果,其中musician.{name|biography}football_team.{name|wiki} 匹配(全文)+royal musician

标签: performance search full-text-search


【解决方案1】:

您可以使用带有tsearch2 列的搜索表,这将允许您进行全文搜索以及您需要查询的每一列:例如名称和位置。

如果您的表都继承自同一个模型,那么在搜索表中引用它们会更容易。如果没有,您可以构建一个内容类型表来放置通用外键,这些外键将在您的搜索表中用于引用最终允许检索查询结果的结果行。该表使用触发器填充。这可能是最有效的解决方案,尤其是如果您非常了解 SQL(可能是 PL/SQL)。

如果不是这样,我建议你使用Lucene在Java中构建你需要的索引,并根据需要进行查询。

【讨论】:

    【解决方案2】:

    您有很多不同的要求,没有软件能够满足所有这些要求。

    1. 自定义搜索语法
    2. 多实体搜索
    3. 全文搜索
    4. 语义搜索 (?)

    让我们来谈谈他们中的每一个。

    自定义搜索语法

    您需要一个能够根据用户输入构建格式良好的查询的系统。这个系统不仅能做到+metallica -bieber -> text CONTAIN metallica AND text NOT CONTAIN bieber

    您的示例并不完全准确。系统如何根据“位置:伦敦”找到“阿森纳”?系统如何根据“位置:伦敦”找到“Neil Christian”?

    解决方案:我很确定像 Lucene 这样的系统支持丰富的搜索查询语法。但是,它将是框架语法,而不是您自己的。请注意,指定自己的语法很困难;您将需要构建一个词法分析器、解析器和您自己的翻译到您的搜索框架的查询树中。

    多实体搜索

    您需要一次搜索多个实体。 这对搜索框架来说没有问题。

    但是,您还想定义搜索结构并将其链接回您的实体。这会有点困难,但并非不可能做到。

    全文搜索

    这也很简单。

    语义搜索

    高级搜索框架应该支持语义搜索(例如,LondonQueen 相关,因为它们在某些文本中经常一起出现)。不过,这可能取决于您的训练数据集。

    结论

    难做的不是继承,也不是全文检索。但是,您应该真正定义数据的匹配方式。搜索系统不是魔术,虽然谷歌可能会这样看。搜索依赖于真正的数学;在进一步讨论之前,您应该在语法上指定这些数学规则。

    【讨论】:

      【解决方案3】:

      我假设您没有使用具有本机全文实现的数据库,所以这是一个穷人的解决方案,但它可以让您在使用完整的解决方案(如 Lucene 或任何其他搜索)之前开始并交付一些东西建议的服务可能需要更长的学习时间。

      您可以简单地安排一个不时运行的进程来从所有这些不同的表中获取所有数据并将它们转储到一个“索引”表中,您可以在其中执行搜索而无需所有连接。

      您可以有一个表格,例如:

      eventId - int
      keywords - nvarchar(max)
      location - nvarchar
      start_date - datetime
      end_date - datetime
      

      这样您就可以在一个地方拥有执行搜索所需的一切。对于搜索本身,您可能会在查询中使用 like 运算符获得不错的结果。

      不是人们梦寐以求的最佳搜索平台,但您可以在几个小时内完成工作。

      【讨论】:

      • 虽然我使用的是原生支持全文搜索的数据库,但我正在寻找更强大的解决方案 - 可能是专门用于搜索的软件。
      • 你可能想看看 Lucene 和/或 Solr。如果您想要托管解决方案,请查看websolr.com
      【解决方案4】:

      我看到了三种方法。

      • 迁移到 Couchdb。要进行location + start time 搜索,您可以使用[location, event_start_time] 作为键来构建视图。在搜索期间,您使用?startkey=["london,"05.11.2012"]&endkey=["london", "07.11.2012"] 进行查询。要在 description 上启用全文搜索,您需要构建一个特定的视图,例如 this

      • 构建ElasticSearch 索引。您示例中的搜索只是使用两个数据字段的结构化查询,其中location 是必须的,而事件start time 是一个范围。 elasticsearch 中的全文搜索功能更强大,您可以定义特定的analyzer 来处理数据中的文本。 Elasticsearch 还支持使用地理空间数据进行搜索。

      • 使用Amazon CloudSearch。有一些已知的限制。我列出了一些我不喜欢的:

        • 文档大小小于 1MB。
        • 在一个字段中最多可以指定 100 个值。
        • 未开源。

      对于搜索实现之间的一些比较:

      【讨论】:

        【解决方案5】:

        SQLite 支持全文索引:

        http://sqlite.org/fts3.html

        【讨论】:

          猜你喜欢
          • 2021-01-24
          • 1970-01-01
          • 2011-05-16
          • 1970-01-01
          • 2015-06-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多