Symfony4中如何将DateTime属性序列化为Elasticsearch的date而非text类型
解决Symfony4中FOSElasticaBundle+JMS Serializer日期字段被识别为text的问题
我来帮你搞定这个问题——你遇到的核心矛盾是:JMS Serializer的@Type注解只负责把PHP的DateTimeImmutable对象序列化为字符串,但FOSElasticaBundle并不会自动把这个类型映射到Elasticsearch的date类型,导致ES把字段当成text存储,进而无法正常排序。
下面是几种既能保留JMS Serializer优势(比如分组序列化),又能让ES正确识别dynamic_date为date类型的方案:
方案一:使用FOSElasticaBundle的字段类型注解
直接在实体字段上添加FOSElastica的注解,明确指定该字段在ES中的类型为date。
首先引入FOSElastica的注解命名空间,然后给dynamic_date字段加上@Elastica\Type注解:
use JMS\Serializer\Annotation as Serializer; use FOS\ElasticaBundle\Configuration\Annotation as Elastica; // 引入这个命名空间 ... /** * @Serializer\Type("DateTimeImmutable") * @Serializer\Groups({"article_show", "list", "elastica"}) * @Elastica\Type("date") // 关键:告诉ES这个字段是date类型 * @var \DateTimeImmutable * @Gedmo\Timestampable(on="change", field="state", value="published" ) * @ORM\Column( name="dynamic_date", type="datetimetz_immutable", nullable=true) */ protected $dynamic_date ;
方案二:在配置文件中混合序列化与属性配置
如果你更倾向于用YAML配置而不是注解,可以在FOSElasticaBundle的配置里,既保留JMS序列化的分组配置,又单独给dynamic_date指定ES类型。这样其他字段依然通过JMS序列化处理,仅这个字段单独配置类型:
fos_elastica: serializer: serializer: jms_serializer ... articles: types: article: serializer: groups: [elastica] # 保留JMS序列化分组 properties: dynamic_date: type: "date" # 单独指定该字段的ES类型
方案三:确保JMS序列化的日期格式符合ES要求
有时候即使指定了ES类型,如果JMS输出的日期格式不符合ES的date类型解析规则,也可能出现问题。可以给JMS的序列化指定标准的ISO8601格式,配合上面的类型配置一起使用:
/** * @Serializer\Type("DateTimeImmutable") * @Serializer\Groups({"article_show", "list", "elastica"}) * @Serializer\DateFormat("Y-m-d\TH:i:sP") # 指定ES能识别的日期格式 * @Elastica\Type("date") * @var \DateTimeImmutable * @Gedmo\Timestampable(on="change", field="state", value="published" ) * @ORM\Column( name="dynamic_date", type="datetimetz_immutable", nullable=true) */ protected $dynamic_date ;
最后一步:重新索引数据
不管用哪种方案,修改配置或注解后都需要重新生成ES索引,执行以下命令:
php bin/console fos:elastica:populate
这样再查看http://local:9200/articles的映射,dynamic_date就会被识别为date类型,排序功能也能正常工作了。
内容的提问来源于stack exchange,提问作者Oepheus
相关产品推荐
相关产品推荐

