Mongoose with CosmosDB: Getting error `Shared throughput collection should have a partition key`

a 夏天 提交于 2019-12-23 10:06:14

问题


I have a node-express application that currently uses Mongoose to connect to MongoDB, and am attempting to migrate it to Azure Cosmos DB.

When I simply allow Mongoose to create the database, the application works fine, however the database is created with individual collection RU pricing.

If I create a new database with Shared throughput enabled and attempt to use that, I get the error Shared throughput collection should have a partition key

I have tried updating the collection schema to include a shard key like this:

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);
};

However this does not work.

Any ideas on how to create/use a partition key? Alternatively the database is small, so if its possible to remove the requirement for the partition key that would also be fine.


回答1:


Now I don't have an exact answer for this question so no need to accept this unless you feel it's correct.

The best solution I've found so far is that this is due to "Provision Throughput" being checked when the database is created in the Azure console. If you delete and recreate the database with this box not checked (it's right below the input for the database name) then you should no longer encounter this error.




回答2:


You specify it when you're creating a collection in the DB that you've opted in for Shared Throughput.

Collection vs Database

If you're using individual collection pricing, you can set the throughput on the individual collections. If you're using the lesser pricing option, you'd get the shared throughput (at the database level) which is less granular but less expensive.

Details here: https://azure.microsoft.com/en-us/blog/sharing-provisioned-throughput-across-multiple-containers-in-azure-cosmosdb/

Partition keys

If you're using the Shared throughput, you'll need a partition Id for the collection that you're adding.

So - create a DB with Shared throughput (check the checkbox below)

After that when you're attempting to add a new document you should be able to create a partition key.




回答3:


I have yet another not-quite-complete answer for you. It seems like, yes, it is required to use partitioned collections if you are using the shared/db-level throughput model in Cosmos. But it turns out it is possible to create a CosmosDb collection with a partition key using only the MongoDb wire protocol (meaning no dependency on an Azure SDK, and no need to pre-create every collection via the Azure Portal).

The only remaining catch is, I don't think it's possible to run this command via Mongoose, it will probably have to be run directly via the MongoDb Node.js Driver, but at least it can still be run from code.

From a MongoDb Shell:

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

This command is meant to set the sharding key for a collection and start sharding the collection, but in CosmosDb it works to create the collection with the desired partitionKey already set.




回答4:


I have an even little more complete answer. You actually can do it with mongoose. I usually do it like this in an Azure Function:

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))


来源:https://stackoverflow.com/questions/53705816/mongoose-with-cosmosdb-getting-error-shared-throughput-collection-should-have

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!