位置、时间序列、向量、附件与媒体

第 3 课 · 共 7 课 约 8 分钟

geopoint 与 geoshape、时间序列属性、向量、附件、媒体引用、加密文本:各存什么,各有什么限制。

本课目标

读完这一课,你将能够

  • 说出位置、时间序列、向量、附件、媒体引用和加密文本各存什么
  • 写出它们的取值形状,说出各自的限制
  • 判断一个需求该用时间序列属性、向量,还是别的建模方式

位置:geopoint 和 geoshape

上一节的类型表里,有几种存的不是「一个数字或一段文字」。这一节把它们逐个讲清:位置、时间序列、向量,以及附件和媒体。

示例工厂的客户有城市,也有地图上的一个点。这个点就是 geopoint 属性 customer.location,存一个 GeoJSON 点,坐标是常见的经纬度(WGS 84)。

GeoJSON 的坐标是先经度、后纬度,这是最容易写反的地方。苏州大约在东经 120.6、北纬 31.3,所以写成 [120.5853, 31.2989];写反了,点会落到海里。

{ "customerId": "C-1008", "location": { "type": "Point", "coordinates": [120.5853, 31.2989] } }

对象有了 geopoint,搜索里就能用 withinDistanceOf(离某个点多远以内)和 withinBoundingBox(在某个方框里),「离这家工厂 50 公里内的客户」变成一步查询。

geoshape 存线和面,比如厂区边界、配送路线。写它要守 GeoJSON 的规则:只能是 LineString、Polygon、MultiLineString、MultiPolygon 或 MultiPoint,不能是 Feature、FeatureCollection 或 GeometryCollection;多边形要闭合,外环逆时针,不能自己交叉。单个点别用 geoshape,用 geopoint。geopoint 能做标题键,geoshape 不能。

时间序列:随时间变化的读数

设备每分钟报一次振动和温度,一天就是 1,440 个读数。这些读数不该变成一个个对象,也不该塞进数组,它们属于 timeseries 属性。

随口一问

每分钟一个读数,建成 reading 对象:一台设备一年就是 50 多万个对象,全是同一种东西。

好的交代

machine.vibration 和 machine.temperature 是两个 timeseries 属性。越线这件事(一次报警)才值得建成对象。

时间序列属性存的不是一个值,而是一条序列,值写成 { seriesId },读取时按需取点:firstPoint、lastPoint 或 streamPoints。它不能做主键或标题键,也不能放进数组。对象的值里还可以直接带上最多 1,000 个点:

{
  "machineId": "M-0007",
  "vibration": {
    "seriesId": "M-0007-vibration",
    "points": [
      { "time": "2026-09-28T08:00:00Z", "value": 2.4 },
      { "time": "2026-09-28T08:01:00Z", "value": 2.6 }
    ]
  }
}

每台设备都有振动和温度读数,所以它们直接放在 machine 上,「这台设备最新的振动」就成了一个属性的一次读取。读最新一点用 lastPoint。新本体集成使用已有对应端点的 /api/v2 接口。时间序列尚无可用的 v2 后继,不能只把旧地址的 v1 换成 v2。如果读数只有一部分设备才有,比如只有几台带流量计,就别在 machine 上加一堆大多为空的时间序列属性,而是另建一个传感器对象类型,再用关系连到设备。

向量:给相似性搜索用

向量(vector)是一串数字,通常是一段文字的嵌入:意思相近的文字,向量也靠得近。给缺陷的描述配一个向量,就能问「找出和这条最像的缺陷」,不用靠关键词碰运气。

缺陷的 description 由质检员随手写,措辞各不相同,正适合用向量找相似。给 defect 加一个向量属性:

{ "name": "descriptionVector", "type": "vector", "vectorDimension": 768, "title": "Description embedding" }
  • 定义里要写 vectorDimension(维数),由生成向量的模型决定,例如 768。只有同一个模型生成的向量才能互相比较;维数不要超过 2048,这是通行的上限。
  • 向量不能做主键或标题键,也不能放进数组。
  • 向量不能筛选、不能比大小,只能做最近邻搜索。
  • 向量又长又不好读,不明确选取它,读对象时不会带上。

附件、媒体引用与加密文本

ATTACHMENT

附件

存一个文件,例如供应商的资质证书。值是 { rid },不能做主键或标题键。

MEDIA

媒体引用

指向一张图片、一段视频或音频,例如质检照片 inspection.photo。值是 { mimeType, reference }。

CIPHER

加密文本

存一段经加密服务编码的字符串,例如联系电话。可以做标题键,不能做主键。

三者的共同点是:属性里只有一个指针或一段密文,真正的文件和明文在别处。

下一节讲怎样在一个属性里放几个字段,以及让多个对象类型共用同一个属性定义。

要点

  • geopoint 存一个点,GeoJSON 先经度后纬度;geoshape 存线和面,单个点别用它。
  • 时间序列属性存一条读数序列,用 firstPoint、lastPoint、streamPoints 读;不能做键,也不能放进数组。
  • 每个对象都有的读数放在对象上;只有部分对象才有的,另建传感器对象。
  • 向量只能做最近邻搜索,要给维数,不能做键,也不能放进数组。
  • 附件、媒体引用、加密文本的值形状能存能读。附件上传和 Media sets 已提供;解密与地理时序服务仍未实现。

练一练

给设备和缺陷补上特殊类型

示例工厂的设备有振动和温度读数,缺陷有一段文字描述。

为 machine 写 vibration 和 temperature 两个 timeseries 属性的定义,再造一条带两个点的取值。

小测

选一个答案,马上看解析。

Q1苏州(东经 120.5853,北纬 31.2989)的 geopoint 怎么写?

Q2设备每分钟一个温度读数,一台设备一年 50 多万个点。怎么建模?

Q3下面哪个类型可以做标题键?

延伸阅读