Spring Data MongoDB 教程

时间序列

时间序列集合是 MongoDB 5.0 版本新增的功能,它有效地存储了一段时期内的测量序列。时间序列数据是随着时间收集的任何类型的数据,并由一个或多个不变参数唯一标识, 这些不变参数通常又称为是数据源的元数据。

与普通集合相比,将时序数据存储在时序集合中提高了查询效率,减少了时序数据和次级索引(secondary index)的磁盘存储空间。

创建时间序列集合的命令:

db.createCollection( <name>,
{
  timeseries: {                  // Added in MongoDB 5.0
     timeField: <string>,        // required for time series collections
     metaField: <string>,
     granularity: <string>
  },
 expireAfterSeconds: <number>,
}
)

说明:

  • name  集合的名称

  • timeseries.timeField  必选参数,每个时间序列文档中包含日期的字段的名称。时间序列集合中的文档必须具有有效的 BSON 日期作为 timeField 的值。

  • timeseries.metaField  可选参数,每个时间序列文档中包含元数据的字段的名称。指定字段中的元数据应该是用于标记一系列唯一文档的数据。元数据应该很少(如果有的话)改变。指定字段的名称不可以是 _id 或与 timeseries.timeField 相同。元数据的字段可以是任何数据类型。

  • timeseries.granularity  可选参数,可选值为 "second", "minute", "hours", 默认值是 "seconds"。手动设置 granularity 参数以通过优化时间序列集合中的数据在内部存储的方式来提高性能。选择与连续传入测量之间的时间跨度最接近的 granularity 参数值来匹配。如果指定了 timeseries.metaField,则要考虑连续的传入的测量值和指定的 metaField 字段具有相同唯一值的时间跨度。如果测量值来自同一来源,则它们通常具有相同的唯一值。如果未指定 timeseries.metaField,请考虑插入集合中的所有测量值之间的时间跨度

  • expireAfterSeconds  可选参数 ,通过指定文档过期的秒数来启用时间序列集合中文档的自动删除

在向时间序列集合插入任何数据之前,我们需要手动将集合创建为时间序列类型的集合。你可以通过运行 db.createCollection 命令定义时间序列集合选项,或者从 @TimeSeries 注解中提供选项来创建时间序列集合。

创建时间序列集合

通过 CollectionOptions 创建

使用 CollectionOptions 创建一个时间序列集合,例如:

template.createCollection("weather", CollectionOptions.timeSeries("timestamp"));

通过驱动创建

使用 MongoDB 驱动创建一个时间序列集合,例如:

template.execute(db -> {
   // 创建名为 weather 的时间序列
   com.mongodb.client.model.CreateCollectionOptions options = new CreateCollectionOptions();
   options.timeSeriesOptions(new TimeSeriesOptions("timestamp"));
   db.createCollection("weather", options);
   return "OK";
});

通过注解创建

使用 @TimeSeries 注解创建一个时间序列集合,如下:

@TimeSeries(collection="weather", timeField = "timestamp")
public class Measurement {
   String id;
   Instant timestamp;
   // ...
}

template.createCollection(Measurement.class);

完整示例

(1)application.properties 配置文件

# Log
logging.level.root=debug

# MongoDB
spring.data.mongodb.uri=mongodb://localhost:27017/test

(2)配置类

package com.hxstrive.springdata.mongodb.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;

/**
* 配置 MongoTemplate
* @author hxstrive.com
*/
@Slf4j
@Configuration
public class AppConfig {

   @Bean
   public MongoTemplate mongoTemplate(MongoDatabaseFactory mongoDatabaseFactory) {
       log.info("mongoTemplate({}, {})", mongoDatabaseFactory);
       return new MongoTemplate(mongoDatabaseFactory);
   }

}

(3)实体定义

package com.hxstrive.springdata.mongodb.entity;

import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.TimeSeries;

import java.time.Instant;

@Data
@ToString
@Builder
@TimeSeries(collection="weather", timeField = "timestamp", metaField = "name")
public class Measurement {
   private String id;
   private Instant timestamp;
   private String name;
}

(4)客户端代码

package com.hxstrive.springdata.mongodb;

import com.hxstrive.springdata.mongodb.entity.Measurement;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.CreateCollectionOptions;
import com.mongodb.client.model.TimeSeriesOptions;
import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.CollectionOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import java.time.Instant;
import java.util.List;


@SpringBootTest
class TimeSeriesDemo {

   @Autowired
   private MongoTemplate mongoTemplate;

   @BeforeEach
   public void init() {
       mongoTemplate.dropCollection("weather");
   }


   /**
    * 通过 CollectionOptions 创建时间序列集合
    */
   @Test
   public void createByCollectionOptions() {
       MongoCollection<Document> doc = mongoTemplate.createCollection("weather",
               CollectionOptions.timeSeries("timestamp"));
       System.out.println(doc);
   }


   /**
    * 通过 MongoDB 驱动创建时间序列集合
    */
   @Test
   public void createByDriver() {
       String str = mongoTemplate.execute(db -> {
           // 创建名为 weather 的时间序列
           com.mongodb.client.model.CreateCollectionOptions options = new CreateCollectionOptions();
           options.timeSeriesOptions(new TimeSeriesOptions("timestamp"));
           db.createCollection("weather", options);
           return "OK";
       });
       System.out.println(str);
       // 结果:
       // OK
   }


   /**
    * 通过注解创建时间序列集合
    */
   @Test
   public void createByAnnotation() {
       MongoCollection<Document> doc = mongoTemplate.createCollection(Measurement.class);
       System.out.println(doc);
   }


   /**
    * 创建集合、插入数据和查询数据
    */
   @Test
   public void simpleDemo() {
       // 创建集合
       mongoTemplate.createCollection(Measurement.class);

       // 写入数据
       mongoTemplate.insert(Measurement.builder().id("100").name("Bauer").timestamp(Instant.now()).build());
       mongoTemplate.insert(Measurement.builder().id("200").name("Helen").timestamp(Instant.now()).build());
       mongoTemplate.insert(Measurement.builder().id("300").name("Bill").timestamp(Instant.now()).build());

       // 查询数据
       List<Measurement> list = mongoTemplate.find(
               Query.query(Criteria.where("id").in("100", "200", "300")), Measurement.class);
       for(Measurement item : list) {
           System.out.println(item);
       }

       // 结果:
       // Measurement(id=100, timestamp=2023-05-23T02:21:45.688Z, name=Bauer)
       // Measurement(id=200, timestamp=2023-05-23T02:21:45.852Z, name=Helen)
       // Measurement(id=300, timestamp=2023-05-23T02:21:45.868Z, name=Bill)
   }
   
}
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号