忽略Elasticsearch中的空格

时间:2017-09-25 10:02:16

标签: elasticsearch spring-data-elasticsearch

对于我的搜索,我想考虑以下事实:"space"字符在过滤请求中不是强制性的。
例如:
当我在"THE ONE"上过滤时,我会看到相应的文件 即使我写"THEONE",我也希望看到它 这就是今天我的查询的构建方式:

boolQueryBuilder.must(QueryBuilders.boolQuery()
     .should(QueryBuilders.wildcardQuery("description", "*" + 
         searchedWord.toLowerCase() + "*"))
     .should(QueryBuilders.wildcardQuery("id", "*" + 
         searchedWord.toUpperCase() + "*"))
     .should(QueryBuilders.wildcardQuery("label", "*" + 
         searchedWord.toUpperCase() + "*"))
     .minimumShouldMatch("1"));

我想要的是添加此过滤器:(Writing a space-ignoring autocompleter with ElasticSearch

"word_joiner": {
  "type": "word_delimiter",
  "catenate_all": true
}   

但我不知道如何使用API​​来做到这一点。 有什么想法?
谢谢!

编辑:根据@ raam86建议,我添加了自己的自定义分析器:

{
    "index": {
      "number_of_shards": 1,
      "analysis": {
        "filter": {
          "word_joiner": {
            "type": "word_delimiter",
            "catenate_all": true
          }
        },
        "analyzer": {
          "custom_analyzer": {
            "type": "custom",
            "tokenizer": "standard",
            "filter": [
              "word_joiner"
            ]
          }
        }
      }
    }
}

以下是文件:

@Document(indexName = "cake", type = "pa")
@Setting(settingPath = "/elasticsearch/config/settings.json")
public class PaElasticEntity implements Serializable {
   @Field(type = FieldType.String, analyzer = "custom_analyzer")
    private String maker;
}

仍然没有工作......

1 个答案:

答案 0 :(得分:0)

您需要shingle token filter。简单的例子。

<强> 1。使用设置创建索引

PUT joinword
{
    "settings": {
        "analysis": {
            "filter": {
                "word_joiner": {
                    "type": "shingle",
                    "output_unigrams": "true",
                    "token_separator": ""
                }
            },
            "analyzer": {
                "word_join_analyzer": {
                    "type": "custom",
                    "tokenizer": "standard",
                    "filter": [
                        "lowercase",
                        "word_joiner"
                    ]
                }
            }
        }
    }
}

<强> 2。检查分析仪是否按预期工作

GET joinword/_analyze?pretty
{
  "analyzer": "word_join_analyzer",
  "text": "ONE TWO"
}

<强>输出:

{
  "tokens" : [ {
    "token" : "one",
    "start_offset" : 0,
    "end_offset" : 3,
    "type" : "<ALPHANUM>",
    "position" : 0
  }, {
    "token" : "onetwo",
    "start_offset" : 0,
    "end_offset" : 7,
    "type" : "shingle",
    "position" : 0
  }, {
    "token" : "two",
    "start_offset" : 4,
    "end_offset" : 7,
    "type" : "<ALPHANUM>",
    "position" : 1
  } ]
}

现在,您可以通过onetwoonetwo找到此文档。搜索将不区分大小写。

Working Spring示例

完整项目available on GitHub

<强>实体:

@Document(indexName = "document", type = "document", createIndex = false)
@Setting(settingPath = "elasticsearch/document_index_settings.json")
public class DocumentES {
    @Id()
    private String id;
    @Field(type = String, analyzer = "word_join_analyzer")
    private String title;

    public DocumentES() {
    }

    public DocumentES(java.lang.String title) {
        this.title = title;
    }

    public java.lang.String getId() {
        return id;
    }

    public void setId(java.lang.String id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public java.lang.String toString() {
        return "DocumentES{" +
                "id='" + id + '\'' +
                ", title='" + title + '\'' +
                '}';
    }
}

主要

@SpringBootApplication
@EnableConfigurationProperties(value = {ElasticsearchProperties.class})
public class Application implements CommandLineRunner {
    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }

    @Override
    public void run(String... args) throws Exception {
        elasticsearchTemplate.createIndex(DocumentES.class);
        elasticsearchTemplate.putMapping(DocumentES.class);

        elasticsearchTemplate.index(new IndexQueryBuilder()
                .withIndexName("document")
                .withType("document")
                .withObject(new DocumentES("ONE TWO")).build()
        );

        Thread.sleep(2000);
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withIndices("document")
                .withTypes("document")
                .withQuery(matchQuery("title", "ONEtWO"))
                .build();

        List<DocumentES> result = elasticsearchTemplate.queryForList(query, DocumentES.class);

        result.forEach (System.out::println);

    }
}