搜索文本以匹配大量字符串

时间:2017-02-15 16:59:42

标签: search elasticsearch indexing lucene pattern-matching

我有一个用例,我必须检查我收到的文本是否包含我拥有的300万个字符串中的任何一个。

我尝试了正则表达式匹配,但是一旦字符串列表越过50k,性能就越差

我正在为搜索列表中的每个单词执行此操作

inText = java.util.regex.Pattern.compile("\\b" + findStr + "\\b",
         java.util.regex.Pattern.CASE_INSENSITIVE).matcher(intext).replaceAll(repl);

我知道我们可以使用像lucene这样的搜索索引,但我觉得那些主要用于从预定义文本中搜索特定文本,但我的用例是相反的,我需要发送一个大文本并检查是否有任何前文本中有定义的字符串

1 个答案:

答案 0 :(得分:1)

我想,你可以采取相反的方式。您的预定义字符串是存储在倒排索引中的文档,您的传入文本是一个查询,您将根据文档进行测试。由于预定义的字符串不会发生太大变化,因此性能非常高。

我准备了一些Elasticsearch代码,可以解决问题。

    public void add(String string, String id) {
        IndexRequest indexRequest = new IndexRequest(INDEX, TYPE, id);
        indexRequest.source(string);
        index(INDEX, TYPE, id, string);
    }

    @Test
    public void scoring() throws Exception {
        // adding your predefined strings
        add("{\"str\":\"string1\"}", "1");
        add("{\"str\":\"alice\"}", "2");
        add("{\"str\":\"bob\"}", "3");
        add("{\"str\":\"string2\"}", "4");
        add("{\"str\":\"melanie\"}", "5");
        add("{\"str\":\"moana\"}", "6");

        refresh(); // otherwise we would not anything

        indexExists(INDEX); // verifies that index exists
        ensureGreen(INDEX); // ensures cluster status is green


        // querying your text separated by space, if the hits length is bigger than 0, you're good
        SearchResponse searchResponse = client().prepareSearch(INDEX).setQuery(QueryBuilders.termsQuery("str", "string1", "string3", "melani")).execute().actionGet();
        SearchHit[] hits = searchResponse.getHits().getHits();

        assertThat(hits.length, equalTo(1));

        for (SearchHit hit: hits) {
            System.out.println(hit.getSource());
        }

    }