Elasticsearch is easy to use

ES client creation and reference

RestHighLevelClient way
@Bean
public RestHighLevelClient restHighLevelClient(a) {
    return new RestHighLevelClient(
            RestClient.builder(
                    Arrays.stream(StringUtils.split(ipAddress,
                                                    ",")).map(HttpHost::create).toArray(HttpHost[]::new))); }// Use by reference
@Resource
private RestHighLevelClient restHighLevelClient;
Copy the code
ElasticsearchTemplate way
@Resource
private ElasticsearchTemplate elasticsearchTemplate;
Copy the code
SpringbootData Repository way
1. Entity objects
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = CenterShopifyMailAnalysisMessageDO.INDEX_NAME)
public class CenterShopifyMailAnalysisMessageDO {
    
    /** * index name */
    public static final String INDEX_NAME = "shopify_mail_analysis_message";

    /** * primary key */
    @Id
    private String id;
}
Copy the code
2. Create Mapper
@Repository
public interface CenterShopifyMailAnalysisMessageRepository extends ElasticsearchRepository<CenterShopifyMailAnalysisMessageDO.String> {
    /** * original index ID **@param refOriginalMessageId
     * @return CenterShopifyMailAnalysisMessageDO
     */
    CenterShopifyMailAnalysisMessageDO findByRefOriginalMessageId(String refOriginalMessageId);


    /** * Query the total number of entries **@returnThe total number of article * /
    int countAllBy(a);

}
Copy the code
3. Use references
@Resource
private CenterShopifyMailAnalysisMessageRepository centerShopifyMailAnalysisMessageRepository;
Copy the code

ES Query common methods

methods instructions
filter No score calculation, high query efficiency, cache (recommended)
must To calculate the score, the query is inefficient and has no cache
must_not Conditions do not need to be met
term There is no word segmentation for the input
match The input content will be word segmentation
matchPhrase Phrase matching query, the ES engine first analyzes the query string and constructs the phrase query from the analyzed text, which means that all participles in the phrase must be matched and the relative positions of each participle remain unchanged
wildcard Wildcard query, * : indicates o or more characters,? : indicates a single character. Similar to mysqllikeThe query
range Gte: greater than or equal to, gt: greater than, LTE: less than or equal to, lt: less than, from-to: between
exists Query whether the file contains thefieldThe specified field, for example: query is notnull: builder must (QueryBuilders existsQuery (” field name “)); Query not empty string Builder.mustnot (QueryBuilders. TermQuery (” field name “, “”));
prefix Match word segmentation prefix If the field has no word segmentation, match the entire field prefix
idx Query by ID
FetchSourceFilterBuilder: The object can set which properties to output and which not to outputCopy the code
Script: can be used as a query or a sort query:// Query the current time. -sentDateTime >= 86400000
Script script = new Script("new Date().getTime() - doc['sentDateTime'].value >= 86400000"); builder.filter(QueryBuilders.scriptQuery(script)); Sorting:// If replyStatus is 0,sentDateTime is sorted from highest to highest; if replyStatus is not 0,sentDateTime is sorted from highest to lowest
Script script = new Script("if(doc['replyStatus'].value == 0){return doc['sentDateTime'].value * -1 }else{return doc['sentDateTime'].value}");

ScriptSortBuilder scriptSortBuilder = SortBuilders.scriptSort(script, ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.DESC);

SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(builder)
                .withSort(scriptSortBuilder
                .build();
Copy the code

ES Query Example

The term query:

Term does precise queries that can be used to handle numbers, booleans, dates, and text. This is not a problem when querying numbers, but it is a problem when querying strings. The implication of the term query is that termQuery looks for the exact term in the inverted index, but it is unaware of the presence of a participle. Term represents a document with a keyword in the query field, and terms represents a document with multiple keywords in the query field. That is, a term for a field is essentially a fuzzy query, except that the search input string is not segmented. If you want to query data through TERM, the field queried by term must have the same index word in the index library as the term query condition; otherwise, the result cannot be queried.

The default IK word splitter for ElasticSearch will slice each word, so if you want to search for a whole word, or a whole sentence, there will be no result.

About the keyword:

I read some articles that say that this property is set for keyword search, not word segmentation. For fields of type string, ES generates a keyword field by default for precise searching. Some say that the keyword is actually still segmented, but the keyword setting adds an extra field, which is filename.keyword. The keyword is a keyword index field that does not know the word. Index also indexes the field to generate a true exact match. As for the segmentation of the word experiment is good. Keyword Does not know the word, but filename will still be a keyword.

public ResponseResult<List<CenterShopifyMailAnalysisMessageVO>> queryPage(CenterShopifyEmailReqVO entity) {
    BoolQueryBuilder builder = QueryBuilders.boolQuery();
    // Exact query
    builder.filter(QueryBuilders.termQuery("websiteId", entity.getWebsiteId()));
    
    // If the term string is queried accurately, use the keyword
    // Exact query for strings
    builder.filter(QueryBuilders.termQuery("name.keyword", entity.getName));
    
    // Time range query, between
    builder.filter(QueryBuilders.rangeQuery(CenterShopifyMailConstant.SENT_DATETIME)
                   .from(DateUtil.parseDateTime(entity.getStartTime()).getTime())
                   .to(DateUtil.parseDateTime(entity.getEndTime()).getTime()));
    
    // Sender, fuzzy query, such as '%xx%'
    builder.filter(QueryBuilders.wildcardQuery("sendAddress.keyword"."*" + 
                                               centerShopifyEmailReqVO.getFromBy() + "*"));
    
    // theme, fuzzy query, default Chinese word segmentation, and like are different
    builder.filter(QueryBuilders.matchPhraseQuery("subject", entity.getSubject()));
    
    And (orderNo=xx or orderNo=xx)
    BoolQueryBuilder order = new BoolQueryBuilder();
    entity.getOrderNoList().forEach(o -> order.should(QueryBuilders.matchPhraseQuery("orderNo", o)));
    builder.filter(order);
    
    // Tag For example: and (refLabelId like '%xx%' and refLabelId like '%xx%')
    entity.getLabelIds().forEach(o ->
                    builder.must(QueryBuilders.wildcardQuery("refLabelId.keyword"."*" + o +"*")));
    
    if (centerShopifyEmailReqVO.getFinishStart() == 3) {
        // Not processed within 24 hours
        Script script = new Script("new Date().getTime() - doc['sentDateTime'].value < 86400000");
        builder.filter(QueryBuilders.scriptQuery(script));
    } else if (centerShopifyEmailReqVO.getFinishStart() == 4) {
        // It has not been processed for more than 24 hours
        Script script = new Script("new Date().getTime() - doc['sentDateTime'].value >= 86400000");
        builder.filter(QueryBuilders.scriptQuery(script));
    }
    
    ReplyStatus =0,sentDateTime sorted from smallest to largest, equal to 0 times -1 in order to adjust the value returned
    // replyStatus≠0,sentDateTime sorted from highest to lowest,
    Script script = new Script("if(doc['replyStatus'].value == 0){return doc['sentDateTime'].value * -1 }else{return doc['sentDateTime'].value}");
    ScriptSortBuilder scriptSortBuilder = SortBuilders.scriptSort(script,
                                          ScriptSortBuilder.ScriptSortType.NUMBER).order(SortOrder.DESC);

    // The body setting does not output
    FetchSourceFilterBuilder fetchSourceFilterBuilder = new FetchSourceFilterBuilder();
    fetchSourceFilterBuilder.withExcludes(CenterShopifyMailConstant.BODY);

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(builder)
            .withSort(SortBuilders.fieldSort(CenterShopifyMailConstant.STATUS).order(SortOrder.ASC))
            .withSort(scriptSortBuilder)
            .withSourceFilter(fetchSourceFilterBuilder.build())
            .withPageable(PageRequest.of(entity.getCurrentPage() - 1, entity.getPageSize()))
            .build();

    AggregatedPage<CenterShopifyMailAnalysisMessageDO> centerShopifyMailAnalysisMessageDOS =
                               elasticsearchTemplate.queryForPage(searchQuery,
                                                                  CenterShopifyMailAnalysisMessageDO.class);
   	
    // content returns data, getTotalElements Total elements
    return ResponseResult.successPage(content, centerShopifyMailAnalysisMessageDOS.getTotalElements(),
                                      centerShopifyEmailReqVO.getCurrentPage(),
                                      centerShopifyEmailReqVO.getPageSize());
}
Copy the code