当 ms 为 .0000000Z 时,CosmosDb 搜索毫秒精度的日期时间不起作用

问题描述 投票:0回答:1

CosmosDB 中有以下测试数据。

{
    "LastSuccessfulDeployment": "2022-10-08T01:30:30.0000000Z",
},
{
    "LastSuccessfulDeployment": "2022-10-08T01:30:30.3816486Z",
}

搜索“2022-10-08T01:30:30.0000000Z”不会返回任何记录,而搜索“2022-10-08T01:30:30.3816486Z”时会返回记录。

protected override IQueryable<Component> ApplyFiltersOnQueryInternal(IQueryable<Component> query, IFilter<Component> filter)
{
    if (filter == null)
        return query;

    var componentFilter = (filter as ComponentFilter)!;

    if (componentFilter.LastSuccessfulDeployment.HasValue)
        query = query.Where(x => x.LastSuccessfulDeployment == componentFilter.LastSuccessfulDeployment);

    return query
        .Skip((componentFilter.CurrentPage - 1) * componentFilter.PageSize)
        .Take(componentFilter.PageSize);
}

EntityQueryable 调试视图:

-- @__componentFilter_LastSuccessfulDeployment_0='08/10/2022 01:30:30'
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Component") AND (c["LastSuccessfulDeployment"] = @__componentFilter_LastSuccessfulDeployment_0))
-- @__componentFilter_LastSuccessfulDeployment_0='12/10/2022 15:18:14'
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Component") AND (c["LastSuccessfulDeployment"] = @__componentFilter_LastSuccessfulDeployment_0))
```Code
datetime .net-core azure-cosmosdb azure-cosmosdb-sqlapi
1个回答
0
投票

如果查询中使用的日期时间没有毫秒,cosmosdb v3 SDK 中的 Linq 查询似乎不会将毫秒放入查询中。

Linq 查询,例如

var testTime = DateTime.Parse("2023-04-16T21:53:56Z").ToUniversalTime();

query
  .Where(x => x.MyTime >= testTime) 
  .OrderBy(x => x.MyTime)
  .Take(1);

将生成以下SQL

SELECT TOP 1 VALUE root FROM root WHERE ((root["MyTime"] >= "2023-04-16T21:53:56Z")) ORDER BY root["MyTime"] ASC

虽然我在 cosmosdb 中有一条带有

2023-04-16T21:53:56.5Z
的记录,但当查询时间没有毫秒时,该记录不会返回。

将查询更改为

SELECT TOP 1 VALUE root FROM root WHERE ((root["MyTime"] >= "2023-04-16T21:53:56.0Z")) ORDER BY root["MyTime"] ASC

记录被返回。在我看来,cosmosdb 会根据查询中日期时间的精度来选择查询精度。


您可以全局更改 Newtonsoft JSON 序列化器的日期,或在每个属性的注释中更改。下面示例中的格式将始终包含 7 ms 数字。

JsonConvert.DefaultSettings = () =>
{
   var settings = new JsonSerializerSettings()
   {
      Converters = new List<JsonConverter>()
      {
         new IsoDateTimeConverter() 
         {
            DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fffffffZ"
         }
      }
   };
   return settings;
};

即使您定义了不使用 newtonsoft 的自定义序列化器,这也可以工作。自定义序列化程序不用于 LINQ 查询。它总是使用 Newtonsoft 来实现这一点。


请注意,您还应该将日期时间存储为

yyyy-MM-ddTHH:mm:ss.fffffffZ
。仅针对查询调整它并不足以满足所有情况。后来遇到了另一个类似的问题,如果不更改日期的存储方式,该问题也无法解决。 3 毫秒的位置对于许多应用程序来说可能就足够了,因为 JavaScript 将在 3 毫秒点处中断。但查询和写入都必须保持一致。微软自己似乎推荐这种格式
yyyy-MM-ddTHH:mm:ss.fffffffZ
用于在cosmosdb中存储日期。

© www.soinside.com 2019 - 2024. All rights reserved.