如何在sql-server数据库表上构建自由流搜索?

时间:2018-05-10 16:42:35

标签: java sql-server elasticsearch lucene

我正在创建一个类似于quora / stackoverflow的Web应用程序,允许用户在问题库上执行CRUD操作(问题库非常小,每个问题最多5个答案约500个问题)以及搜索。如何在问题库上建立自由流量搜索或自动建议功能?

Tech Stack:

  1. CRUD操作的Restful服务是在tomcat上托管的基于Java EE(spring boot)的服务器上公开的。
  2. 前端应用程序是使用React构建的,并由Node服务器提供。
  3. 使用的数据库是SQL Server。
  4. 问题库架构:

    questionId: String
    
    tags: [String]
    
    title: String
    
    description: String
    
    answernotes: [String]
    
    applicableJobRole: [Intern, Full Time]
    
    state: [Approved, UnderReview, Obsolete]
    
    difficultyLevel: [Easy, Medium, Hard]
    
    noOfTimesUsed: int
    
    createdBy: user
    

    要求:

    对于我的网络应用程序,我想在问题库上构建自由流量搜索或自动建议功能(在问题库中搜索现有问题,如描述,标题,答案备注等)。这是为了防止在问题库中创建重复的问题,并帮助用户搜索类似的问题。

    对于前。类似于下图的内容(从Quora剪下来)。

    的问题:

    1. 弹性搜索是否适合索引或为这么小的数据集构建搜索功能?或者,
    2. 我应该使用自己创建的数据结构(如应用程序服务器本身中的后缀树)来构建索引吗?
    3. 是否有其他一些快速使用推荐的解决方案来构建这种用例的自由流搜索功能?

      这里的潜在客户/指针表示赞赏。

      Search from Quora

4 个答案:

答案 0 :(得分:5)

  

我应该在应用服务器本身使用自己创建的数据结构(如后缀树)构建索引吗?

请不要!这将花费很长时间,并且可能极易出错。在应用程序服务器本身中管理索引可能是一个可行的解决方案,但使用库肯定会对您有所帮助。

虽然有可能使用Elasticsearch,但可以使用简单的Lucene索引轻松管理这些数据量。此决策还取决于您要为系统确保的冗余。如果您对每次服务器关闭时无法访问某项服务感到不满意,则应查看Lucene的索引复制功能或使用冗余Elasticsearch安装。

答案 1 :(得分:1)

  

弹性搜索是否适合索引或构建搜索   这么小的数据集的功能?

是的。我认为您要索引的数据大小不是主要问题。像elasticsearch,solr或lucene这样的库或搜索引擎有一些基本功能,如果你想实现用户友好和最先进的搜索,你真正使用它。如果你不使用其中一个,那么你真的很难用的一些用例:

  • 基于语言的分析(词干)
  • 更好地支持多语言用例
  • 全文搜索
  • Lhevenstein距离的自动建议
  

我应该使用自己创建的数据结构(如后缀)来构建索引   应用程序服务器本身的树?

根据micpalmias回答:他是对的。不要这样做!为此使用搜索引擎/库。我们的设计是为你做的,他们做得非常好。

答案 2 :(得分:1)

ElasticSearch和Solr是很棒的全文搜索服务器,Lucene是一个很棒的全文搜索库,可以用于您的场景。但是,你知道SQL Server有全文搜索功能吗?使用CONTAINS,您可以搜索:

  • 一个单词或短语。
  • 单词或短语的前缀。
  • 靠近另一个词的一个词。
  • 从另一个词中生成的词(例如,词 驱动器是驱动器,驱动器,驱动器和驱动器的弯曲杆 驱动)。
  • 一个单词,是使用同义词库的另一个单词的同义词(for 例如,“金属”一词可以包含诸如“铝”之类的同义词 “钢”)。

为了能够使用CONTAINS,您需要setup Full Text Search

SQL Server全文搜索不像ElasticSearch或Lucene那样花哨或快速,但是:

  • 它是SQL Server的一部分,因此您不需要另一个移动部件。
  • 索引会自动更新。使用ElasticSearch或Lunece,您需要使用某种机制在基表更改时更新索引。
  • 我认为这对你的情况来说已经足够了。

答案 3 :(得分:1)

micpalmia是正确的。对于创建小于问题的小索引应该不需要弹性搜索或Solr。你应该选择lucene-core和lucene。

如果您在java项目中使用maven,则可以在pom.xml中包含以下依赖项。

<!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-core -->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    <version>7.3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-queryparser -->
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-queryparser</artifactId>
    <version>7.3.1</version>
</dependency>

拥有这些库后,您可以将问题编入索引为this code之后的文档。您的文档可以是包含问题ID,标题和说明的简单对象。

private org.apache.lucene.document.Document createDocument
    (String id, String title, String description){
    Document document = new Document();
    document.add(new StringField("id", id, Field.Store.YES));
    document.add(new StringField("title", title, Field.Store.YES));
    document.add(new StringField("description", description, Field.Store.YES));
    return document;
}

在搜索重复的问题时,您会关注this code

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;

private static TopDocs searchByTitle(String title, IndexSearcher searcher) 
throws Exception {
    QueryParser qp = new QueryParser("title", new StandardAnalyzer());
    qp.setAllowLeadingWildcard(true);
    Query titleQuery = qp.parse(title);
    TopDocs hits = searcher.search(firstNameQuery, 10);
    return hits;
}

您还可以告诉您的searchByTitle函数搜索描述

TopDocs docs = searchByTitle(" ( title:" + enteredText + "~ OR title:*" + enteredText + 
    "* ) OR  ( description:" + enteredText + " )", searcher)