有多种方式可以通过注解实现不索引某个字段。以下是几种常用的方法,我会从最推荐的方式开始介绍。


方法一:使用 @Field 注解的 index 属性(最常用、最标准)

这是 Spring Data Elasticsearch 官方推荐的方式,通过设置 index = false 来明确禁止索引该字段。

语法:

@Field(type = FieldType.Text, index = false)
private String secretInfo;

示例:

public class WebMtoPost {
    
    @Id
    private Long id;
    
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title; // 这个字段会被索引,可以搜索
    
    @Field(type = FieldType.Text, index = false)
    private String internalRemark; // 这个字段不会被索引,无法被搜索
    
    // 其他字段...
}

效果:

  • internalRemark 字段会存储在 _source 中(查询结果中可以看到它的值)
  • 无法 通过任何搜索条件(如 match, term 查询)来匹配这个字段的内容
  • 相当于在 Elasticsearch 映射中设置了 "index": false

方法二:使用 @Transient 注解(不推荐用于此目的)

@Transient 注解的意思是"瞬态的",它会告诉 Spring Data Elasticsearch 完全忽略这个字段。

语法:

import org.springframework.data.annotation.Transient;

@Transient
private String temporaryData;

示例:

public class WebMtoPost {
    
    @Id
    private Long id;
    
    private String title;
    
    @Transient
    private String calculatedField; // 这个字段既不会被索引,也不会被存储
}

效果:

  • 该字段 不会出现在 Elasticsearch 文档中
  • 既不能搜索,在查询结果中也看不到这个字段
  • 注意: 这通常用于临时计算字段或不想持久化的字段,如果只是想"不索引但保留存储",请使用方法一。

方法三:使用 @ReadOnlyProperty 注解(Spring Data 通用注解)

这个注解表示该字段是只读的,通常也会导致不被索引。

语法:

import org.springframework.data.annotation.ReadOnlyProperty;

@ReadOnlyProperty
private String readOnlyField;

方法对比总结

方法 注解 效果 适用场景
推荐 @Field(index = false) 字段被存储,但不被索引 需要保留字段值但不希望被搜索(如备注、内部信息)
不推荐 @Transient 字段不被存储也不被索引 临时计算字段、不想持久化的数据
可选 @ReadOnlyProperty 通常不被索引 只读字段

完整示例:在 WebMtoPost 中的应用

@Document(indexName = "mto_post")
public class WebMtoPost {
    
    @Id
    private Long id;
    
    // 可搜索的字段
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title;
    
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String content;
    
    // 不索引但存储的字段(推荐方式)
    @Field(type = FieldType.Text, index = false)
    private String internalNotes; // 内部编辑备注
    
    @Field(type = FieldType.Text, index = false)
    private String auditComments; // 审核意见
    
    // 不被索引且不被存储的字段
    @Transient
    private String wordCountInfo; // 临时统计的字数信息
    
    // 可搜索的关键字字段
    @Field(type = FieldType.Keyword)
    private String status;
    
    // 其他正常字段...
    @Field(type = FieldType.Date)
    private Date createTime;
    
    // getter/setter 省略...
}

验证方法

创建索引后,你可以通过以下方式验证字段是否被正确设置:

  1. 查看索引映射:

    GET /mto_post/_mapping
    
  2. 在返回的映射中,你会看到类似这样的结构:

    {
      "mto_post": {
        "mappings": {
          "properties": {
            "title": {
              "type": "text",
              "analyzer": "ik_max_word"
            },
            "internalNotes": {
              "type": "text",
              "index": false  // 这里显示 index: false
            }
            // ... 其他字段
          }
        }
      }
    }
    

总结

对于"不索引但需要存储"的需求,强烈推荐使用:

@Field(index = false)

这是最语义化、最符合 Elasticsearch 设计意图的方式。