在CosmosDB中存储资产跟踪数据的好方法

时间:2019-07-18 18:03:14

标签: mongodb azure azure-functions azure-cosmosdb

我正在Azure上构建一个简单的资产跟踪应用程序,该应用程序需要捕获周围的详细信息

  1. 资产信息,
  2. 其当前位置
  3. 具有资产ID及其位置的时间序列数据。随时间推移跟踪资产。 可能多年

有问题的资产将以固定的时间间隔流传输其位置详细信息,例如每10秒钟在Event Grid上流一次,我想将此数据流化成档案以供将来进行任何分析,同时时间还可以查询geospatial距离1 km内的其他资产,并向他们发送通知。

因此,我想了解将信息存储在CosmosDB中的最佳方法是,将这种信息有效地存储在一个按资产ID划分的资产的集合中

Asset : {
  AssetId : "123456",
  RegisteredAddress : "123, abc xyz",
  ZipCode : "12345"
  MobileNo: "32423432432"
  CurrentLocation: Point {12, 123}
  LocationHistory:[
       {Timestamp: 1/1/2019 12:20:10, Location: Point{12, 123}},
       {Timestamp: 1/1/2019 12:20:20, Location: Point{12, 123}},
       {Timestamp: 1/1/2019 12:20:30, Location: Point{12, 123}},
       {Timestamp: 1/1/2019 12:20:40, Location: Point{12, 123}},
       {Timestamp: 1/1/2019 12:20:50, Location: Point{12, 123}},
]
}

或者最好维护一个单独的集合来管理LocationHistory

LocationHistory: {
 AssetId: 12345, 
 Timestamp: "1/1/2019 12:20:10", 
 Location: Point{12, 123}
}

顺便说一句,我是Document store的新手,所以如有可能,请随时提出一个更好的选择。

我真的希望在这里将我的运营成本降至最低,因此上述两种方法对我的总体运营成本有何影响。假设我使用Azure函数在事件网格事件上触发并更新此集合。

更新1:

基于下面的 Joel Oughton 的回答,我试图将有关资产的元数据以及跟踪详细信息作为单独的文档移动到一个文件中采集。为此,我进行了以下更改:

  1. 我为所有类添加了另外2个属性,即_PartitionKey_Service
  2. 在存储事件之前,我正在构建和更新_PartitionKey

我现在正在使用以下代码来捕获资产元数据:

assetInfo.LastUpdated = DateTimeOffset.Now;
assetInfo._PartitionKey = $"assets_{assetInfo.Address.State.ToLower()}_{assetInfo.Address.City.ToLower()}";
assetInfo._Service = "assets";

Uri collectionUri = UriFactory.CreateDocumentCollectionUri(config.DatabaseName, config.CollectionName);
var documnent = await DBUtility.GetDocumentClient().UpsertDocumentAsync(collectionUri, assetInfo);

以相同的方式存储我在下面使用此代码的跟踪信息:

tracking.UnixTimestamp = DBUtility.GetEpochTimeMillis(DateTime.UtcNow);
tracking.Id = $"{tracking.AssetId.ToLower()}_{tracking.UnixTimestamp}";
tracking.Timestamp = DateTime.Now.ToString("o");
tracking._PartitionKey = $"tracking_{tracking.AssetId.ToLower()}_{DateTime.Today.ToString("D")}";
tracking._Service = "trackings";

Uri collectionUri = UriFactory.CreateDocumentCollectionUri(config.DatabaseName, config.CollectionName);
var documnent = await DBUtility.GetDocumentClient().UpsertDocumentAsync(collectionUri, tracking);
requestCharge += documnent.RequestCharge;  

此接缝工作良好,但是我很难决定如何从给定坐标中查询所有说1 Km的资产。问题是我需要在使用ST_DISTANCE之前从每个资产中选择最新的跟踪事件。

在这种情况下,有人可以建议我如何创建一个查询,该查询能够找到距给定1 Km最近的坐标Point的所有资产详细信息。

1 个答案:

答案 0 :(得分:0)

Cosmos DB具有文档大小限制,并且对于较大的文档,性能可能会降低。

我将存储一个包含资产ID,地址等的元数据类型文档以及一个包含资产ID,时间戳和位置的文档。

另外,可以使用最新的时间戳位置来确定当前位置,而不必每次更改都更新元数据记录。

此结构将允许高效的读写操作,并防止出现文档大小限制的问题。

如果要优化运营成本并使用.NET,可以使用https://github.com/cloud-maker-ai/Nebula(免责声明:我是作者)。否则,请确保整个RU在多个集合中共享,或者两种文档类型都以逻辑分隔的方式存储在同一集合中。