在 Azure Cosmos DB for MongoDB API 中使用无默认索引策略的 sort() 游标方法
Posted
技术标签:
【中文标题】在 Azure Cosmos DB for MongoDB API 中使用无默认索引策略的 sort() 游标方法【英文标题】:Using the sort() cursor method without the default indexing policy in Azure Cosmos DB for MongoDB API 【发布时间】:2019-11-21 03:29:57 【问题描述】:对于 Cosmos DB for MongoDB API(版本 3.4),以下 find 查询结合游标排序方法似乎表现不正确:
db.test.find("field1": "value1").sort("field2": 1)
如果满足以下所有条件,则会发生错误:
默认索引策略已被丢弃 - 无论之后是否使用 createIndex() 创建了自定义索引。 find() 查询不返回任何文档(Find(filter).Count() == 0) 定义排序顺序的排序文档仅包含一个字段。该字段是否存在或已被索引并不重要。在排序文档中使用两个字段会返回 0 个匹配项,这是正确的行为。如果满足以下所有条件,也会发生错误:
放弃了默认索引策略 find() 查询返回一个或多个文档 排序文档只包含一个字段。该字段尚未编入索引。错误信息:
排除指定order-by项对应的索引路径。
只有在使用 CosmosDB 时才会出现故障,使用本机 MongoDB(mongoDB Atlas,v4.0)它会正常运行。
使用带有 MongoDB 3.4 有线协议(预览功能)的 Azure Cosmos DB for MongoDB API。 MongoDB C#/.NET 驱动程序和 mongo shell 都会出现此问题。
另外,这个问题只出现在 find() 中。包含 $match 和 $sort 的等效聚合管道行为正确。
复制
-
使用“Azure Cosmos DB for MongoDB API”创建一个 Azure Cosmos DB 帐户。启用 MongoDB 3.4 的预览功能(3.2 版尚未测试)。
创建一个新数据库
创建一个新集合,定义一个分片键
删除默认索引策略(使用 db.test.dropIndexes() )
(可选)创建新的自定义索引
(可选)插入文档
在 mongo shell(或具有 mongoDB C#/.NET 驱动程序的等效代码)中执行命令:
db.test.find("field1": "value1").sort("field2": 1)
预期结果
所有符合查询条件的文档。如果没有,则不应退回任何文件。
实际结果
错误:错误: "_t" : "OKMongoResponse", “好”:0, “代码”:2, "errmsg" : "Message: \"Errors\":[\"排除指定order-by项对应的索引路径。\"]\r\nActivityId: c50cc751-0000-0000-0000-000000000000,请求 URI:/apps/[...]/,RequestStats:\r\nRequestStartTime:2019-07-11T08:58:48.9880813Z,RequestEndTime:2019-07-11T08:58:49.0081101Z,尝试的区域数:1 \r\nResponseTime: 2019-07-11T08:58:49.0081101Z, StoreResult: StorePhysicalAddress: rntbd://[...]/, LSN: 359549, GlobalCommittedLsn: 359548, PartitionKeyRangeId: 0, IsValid: True, StatusCode: 400 , SubStatusCode: 0, RequestCharge: 1, ItemLSN: -1, SessionToken: -1#359549, UsingLocalLSN: True, TransportException: null, ResourceType: Document, OperationType: Query\r\n, SDK: Microsoft.Azure.Documents.Common /2.4.0.0", [...]
解决方法
向排序文档添加一个额外的“虚拟”字段可以防止错误:
db.test.find("field1": "value1").sort("field2": 1, "dummyfield": 1).count()
解决方法并不令人满意。它可能会伪造结果。
是我做错了什么,还是 Cosmos DB 的行为有缺陷?
【问题讨论】:
我有同样的问题,虚拟字段解决方法甚至不起作用。 除了使用 dummyfield 之外,你有没有找到新的解决方案? 问题中描述的解决方法似乎仅适用于 3.2/3.4 版,但不适用于 3.6 版。 这个运气好吗? 【参考方案1】:根据 Microsoft 支持,需要在要排序的字段上创建索引。可以删除默认索引并创建自定义索引。至于每次添加新字段时不修改索引的问题,除了执行客户端排序之外,没有其他选择。不幸的是,客户端排序会占用客户端的大量 CPU 内存,并且当您获得更多要索引的字段时,索引排序会起作用。
因此我没有找到真正令人满意的解决方案:
使用默认索引策略。但是,这可能会导致索引过大。 索引所有需要排序的元素。每次必须为新元素编制索引时,都会导致手动修改索引策略。 仅使用客户端排序。在我看来,这会导致 MongoDB 功能受到很大限制。 使用聚合框架而不是 find 方法。这会导致复杂性和流量增加。 迁移到本机 MongoDB。【讨论】:
【参考方案2】:db.collection.createIndex ( "$**" : 1 );
【讨论】:
请在您的答案中添加一些解释,以便其他人可以从中学习 发生了什么,AzureCosmoDB api 无法完成 mongoDB 的所有功能,它需要一个索引来进行搜索。 请通过编辑将所有说明 添加到您的答案 我尝试添加docs.mongodb.com/manual/core/gridfs 中所述的两个索引,即:db.fs.chunks.createIndex( files_id: 1, n: 1 , unique: true );
和db.fs.files.createIndex( filename: 1, uploadDate: 1 );
,但这不起作用。另一方面,您的回答确实有效。如果有人知道原因,请分享您的知识以上是关于在 Azure Cosmos DB for MongoDB API 中使用无默认索引策略的 sort() 游标方法的主要内容,如果未能解决你的问题,请参考以下文章
Cosmos DB 更改源触发 Azure 函数:租赁丢失异常