猫鼬与CosmosDB:收到错误消息“共享吞吐量收集应具有分区键”

时间:2018-12-10 12:38:10

标签: node.js mongoose azure-cosmosdb azure-cosmosdb-mongoapi

我有一个node-express应用程序,当前使用Mongoose连接到MongoDB,并且正在尝试将其迁移到Azure Cosmos DB。

当我仅允许Mongoose创建数据库时,该应用程序可以正常工作,但是该数据库是使用单独的集合RU定价创建的。

如果我创建一个启用了共享吞吐量的新数据库并尝试使用它,则会出现错误Shared throughput collection should have a partition key

我尝试过更新收集模式以包括这样的分片键:

const mongoose = require('mongoose');

module.exports = function() {
  const types = mongoose.Schema.Types;
  const messages = new mongoose.Schema({
    order: { type: types.ObjectId, required: true, ref: 'orders' },
    createdAt: { type: Date, default: Date.now },
    sender: { type: types.ObjectId, required: true, ref: 'users' },
    recipient: { type: types.ObjectId, ref: 'users' },
    text: { type: String, required: true },
    seen: { type: Boolean, default: false },
  }, { shardKey: { order: 1 } });

  return mongoose.model('messages', messages);
};

但是这不起作用。

关于如何创建/使用分区键的任何想法?另外,数据库很小,因此如果可以删除对分区键的要求,那也可以。

4 个答案:

答案 0 :(得分:0)

现在我对这个问题没有确切的答案,因此除非您认为是正确的,否则无需接受。

到目前为止,我找到的最佳解决方案是这是由于在Azure控制台中创建数据库时选中了“ Provision Throughput”。如果您删除并重新创建数据库时未选中此框(该框位于数据库名称输入的正下方),那么您应该不再遇到此错误。

答案 1 :(得分:0)

您在选择共享吞吐量的数据库中创建集合时指定它。

集合与数据库

如果使用单个收藏夹定价,则可以设置单个收藏夹的吞吐量。如果您使用价格较低的选项,则会获得共享吞吐量(在数据库级别),粒度较小但价格较便宜。

此处的详细信息:https://azure.microsoft.com/en-us/blog/sharing-provisioned-throughput-across-multiple-containers-in-azure-cosmosdb/

分区键

如果您使用共享吞吐量,则需要为要添加的集合分配一个分区ID。

因此-创建具有共享吞吐量的数据库(请选中下面的复选框)

之后,当您尝试添加新文档时,您应该可以创建分区键。

答案 2 :(得分:0)

我还有另一个还不太完整的答案。看来,是的,如果您在Cosmos中使用共享/数据库级别的吞吐量模型,则必须使用 分区集合。但是事实证明可以仅使用MongoDb有线协议创建具有分区键的CosmosDb集合(这意味着不依赖Azure SDK,也不需要通过Azure预先创建每个集合门户)。

剩下的唯一收获是,我认为不可能通过通过猫鼬运行此命令,它可能必须直接通过MongoDb Node.js驱动程序运行,但是至少仍然可以通过代码运行。

从MongoDb Shell:

db.runCommand({shardCollection: "myDbName.nameOfCollectionToCreate", 
               key: {nameOfDesiredPartitionKey: "hashed"}})

该命令旨在为集合设置分片密钥并开始对集合进行分片,但是在CosmosDb中,它可以使用已设置的所需partitionKey来创建集合

答案 3 :(得分:0)

我有一个更完整的答案。您实际上可以用猫鼬来做。我通常在Azure函数中这样做:

mongoose.connect(process.env.COSMOSDB_CONNSTR, {
useUnifiedTopology: true,
useNewUrlParser: true,
auth: {
    user: process.env.COSMODDB_USER,
    password: process.env.COSMOSDB_PASSWORD,
},
})
.then(() => {
    mongoose.connection.db.admin().command({
        shardCollection: "mydb.mycollection",
        key: { _id: "hashed" }
    })
    console.log('Connection to CosmosDB successful ?')
})
.catch((err) => console.error(err))