代码之家  ›  专栏  ›  技术社区  ›  Lokesh Agrawal

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

  •  5
  • Lokesh Agrawal  · 技术社区  · 6 年前

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

    技术堆栈:

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

    题库架构:

    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
    

    要求:

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

    例如,与下图类似的东西(摘自Quora)。

    问题:

    1. 弹性搜索是否适合为如此小的数据集建立索引或构建搜索功能?或
    2. 我是否应该使用自建的数据结构(如应用服务器本身的后缀树)构建索引?

    是否有其他快速使用的推荐解决方案可用于为此类用例构建自由流搜索功能?

    在此感谢潜在客户/指导员。

    Search from Quora

    4 回复  |  直到 6 年前
        1
  •  5
  •   Michele Palmia    6 年前

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

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

    虽然Elasticsearch是一种可能性,但可以使用简单的Lucene索引轻松管理这一数量的数据。这一决定还取决于您希望为系统确保的冗余度。如果您对每次关闭一台服务器时都无法访问一个服务感到不满意,那么您应该看看Lucene的索引复制功能或使用冗余的Elasticsearch安装。

        2
  •  1
  •   dom    6 年前

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

    是的,是的。我认为你喜欢索引的数据的大小不是这里的主要问题。如elasticsearch、solr或lucene等库或搜索引擎都有一些基本功能,如果您想实现一个用户友好且最先进的搜索,您可以真正使用这些功能。如果不使用以下其中一个用例,您会遇到一些真正困难的用例:

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

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

    基于迈克尔·帕尔米亚斯的回答:他是对的。不要这样做!为此使用搜索引擎/库。我们的设计就是为你做这件事,他们做得很好。

        3
  •  1
  •   Jesús López Sean Lange    6 年前

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

    • 单词或短语。
    • 单词或短语的前缀。
    • 一个词靠近另一个词。
    • 从另一个单词(例如,单词 驱动器是驱动器、驱动器、驱动器和 驱动)。
    • 使用同义词库的另一个单词的同义词(用于 例如,“金属”一词可以有同义词,如“铝”和 “钢”)。

    能够使用 CONTAINS 你需要 setup Full Text Search

    SQL Server全文搜索没有ElasticSearch或Lucene那么花哨或快速,但:

    • 它是SQL Server的一部分,因此不需要其他移动部件。
    • 索引会自动更新。使用ElasticSearch或Luncee,您需要使用某种机制在基表更改时更新索引。
    • 我认为这对于你的场景来说已经足够了。
        4
  •  1
  •   Prathamesh Jagtap    6 年前

    MichPalmia是对的。对于创建少于个问题的小索引,应该不需要弹性搜索或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)