Getting 'query in command must target a single shard' - azure-cosmosdb

I have a CosmosDB setup using the Mongo API. I have a collection with a hashed shard on one of the field of the document. When I run commands like db.collection.remove or db.collection.deleteMany I get the following error.
Command deleteMany failed: query in command must target a single shard key.: {"message":"Command deleteMany failed: query in command must target a single shard key."}
I'm not sure how can I mention a shard key as part of the query considering I want the query to run across all the shards.

You need to provide shard key when you want to run commands like db.collection.remove or db.collection.deleteMany.
For example :
My data source as below:
[
{
"id" : "2",
"name" : "b"
},
{
"id" : "1",
"name" : "a"
}
]
And my shared key is "/name". Use db.coll.deleteMany({"name":"a"}) to delete specific shard.
Hope it helps you.

It should be ShardKey which you have chosen when you created cosmosDb collection.
FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("id", 2);
=== 2 is my shardKey
await this._dbContext.GetProducts.DeleteOneAsync(filter);
return RedirectToAction("Index");
Kindly refer an image below , how does it look like in CosmosDB

Shard Key(Partition Key) has to be provided during specification of schema model in the code. Once its provided, we can perform regular operation like save, update and delete as usual.
Example:
const mySchema = new Schema({
requestId: { type: String, required: true },
data: String,
documents: [{ docId: String, name: String, attachedBy: String }],
updatedBy: {
type: {
name: { type: String, required: true },
email: { type: String, required: true },
}, required: true
},
createdDate: { type: Date, required: true },
updatedDate: { type: Date },
}, { shardKey: { requestId: 1 } }
);
In the above code we specified requestId as Shard Key, now we can perform any mongo operations
Example:
let request:any = await myModel.findById(requestId);
request.data ="New Data";
await request.save();
Hope that helps.
This works with all Mongo operations

Related

How to check if an entry already exists when posting in Dynamo DB with AWS Amplify

In an Amplify w/ graphql project, I have a conversation schema which both members of the conversation saved in an array. When creating a conversation, I only want one conversation to exists between two users. So I want the creating of the conversation entry to fail when a conversation already exists.
When creating the mutation, I tried to use the condition input to let the query fail when the condition is false. But I have not found a solution to check the members array.
Any advice on using the conditions input is appreciated!
type Conversation
#model {
id: ID!
members: [String!]!
...
}
const createConversationInput: CreateConversationInput = {
members: [userOneId, userTwoId],
...
};
const createConversationMutation = (await API.graphql({
query: createConversation,
variables: {
input: createConversationInput,
condition: {
and: [
{ not: { members: { contains: userOneId } } },
{ not: { members: { contains: userTwoId } } },
],
},
},
...
})) as { data: CreateConversationMutation };

I need to all users and for each user all tokens in sequelize

I have a schema in sequelize that a user has many tokens, I need to get all users and for each user, I need to have all tokens. The id of user is saved in Token table as FK.
I created this below but did not work
await Model.Users.findAll({
attributes: ['id'],
include: [
{
model:Model.Token,
attributes: ['token']
}
]
});
The response I want to have back is like below
[
{ id: 2, Tokens: [{token: sdasdasdasdweqrewrfwe}, {token: test}] },
{ id: 6, Tokens: [{token: test2}, {token: test3}] },
.
.
]
Thanks
Problem was not in code but in sequelize table connection, if you have same problem please check the connection
db.User.hasMany(db.Token, {
onDelete: "CASCADE",
onUpdate: "CASCADE",
foreignKey: 'user_id'
});

400 error when upsert using Cosmos SP

I'm trying to execute the below SP
function createMyDocument() {
var collection = getContext().getCollection();
var doc = {
"someId": "123134444",
};
var options = {};
options['PartitionKey'] = ["someId"];
var isAccepted = collection.upsertDocument(collection.getSelfLink(), doc, options, function (error, resources, options) {
});
}
and cosmos keeps on complaining that there's something wrong with the partition key
{ code: 400,
body: '{"code":"BadRequest","message":"Message: {\\"Errors\\":
[\\"PartitionKey extracted from document doesn\'t match the one specified in the header\\"]}
}
Does anyone have any idea how to pass in the partion key in options so it gets pass this validation ?
Figured it out. The error was with how we call the stored proc.
How we were doing it
client.executeStoredProcedure('dbs/db1/colls/coll-1/sprocs/createMyDocument',
{},
{} //Here you have to pass in the partition key
);
How it has to be
client.executeStoredProcedure('dbs/db1/colls/coll-1/sprocs/createMyDocument',
{},
{"partitionKey": "43321"}
);
I think you misunderstand the meaning of partitionkey property in the options[].
For example , my container is created like this:
The partition key is "name" for my collection here. You could check your collection's partition key.
And my documents as below :
{
"id": "1",
"name": "jay"
}
{
"id": "2",
"name": "jay2"
}
My partitionkey is 'name', so here I have two paritions : 'jay' and 'jay1'.
So, here you should set the partitionkey property to '123134444' in your question, not 'someId'.
More details about cosmos db partition key.
Hope it helps you.

SimpleSchema unable to set specific error message for given validation

I have this very basic model with just one field name that I want to validtate against a regex:
const Projects = new ProjectsCollection('projects');
Projects.schema = new SimpleSchema({
_id : {type: String, regEx: SimpleSchema.RegEx.Id},
name : {
type : String,
regEx: /^[a-zA-Z0-9]+((\s[a-zA-Z0-9]+)|(_[a-zA-Z0-9]+)|(-[a-zA-Z0-9]+)|(\.[a-zA-Z0-9]+))?$/
}
});
Projects.attachSchema(Projects.schema);
When the validation fails I get back a validation error saying that regex failed for Name which is undesirable for me because it's ambiguous and the user has no idea what exactly I need him to enter.
I tried adding the following with no success:
Projects.schema.messages({
"regEx name": [{
msg: "test error message"
}]
});
This one however..works but the problem is that I could have any other model with a name field and it will spit out the same error message for all of them (and I plan on having another model with a name field):
SimpleSchema.messages({
"regEx name": [{
msg: "test error message"
}]
});
I tried also with (no success):
SimpleSchema.messages({
"regEx projects.name": [{
msg: "test error message"
}]
});
I insert via methods and here's my insert code:
export const insert = new ValidatedMethod({
name : 'projects.insert',
mixins : [simpleSchemaMixin],
schema : Projects.simpleSchema().pick([
'name'
]),
schemaValidatorOptions: {
clean : true,
filter: false
},
run({name}) {
return Projects.insert({
name
}, null);
},
});
Any ideas on how am I supposed to configure my validation messages so that I can target them for specific fields?
See the documentation for the special case of regex messages:
In your case you should try:
Projects.schema.messages({
"regEx name": [
{
exp: /^[a-zA-Z0-9]+((\s[a-zA-Z0-9]+)|(_[a-zA-Z0-9]+)|(-[a-zA-Z0-9]+)|(\.[a-zA-Z0-9]+))?$/ ,
msg: "test error message"
}
]
});
This answer and question applies to v1 of meteor-simpl-schema
I had the same problem and this worked for me. I think that custom messages are instance based - are bound only to one simplSchema instance. Then in your validated-method, pick() will create a new SimplSchema instance, without your custom messages.
I needed to manually add a custom messages from the "parent" schema.
In your case like this:
const insertProjectSchema = Projects.schema.pick('name');
insertProjectSchema.messages(Projects.schema._messages);
export const insert = new ValidatedMethod({
name : 'projects.insert',
mixins : [simpleSchemaMixin],
schema : insertProjectSchema,
schemaValidatorOptions: {
clean : true,
filter: false
},
run({name}) {
return Projects.insert({
name
}, null);
},
});

Recording username with meteror autoform

I'm creating a form using cfs:autoform to capture a photo and caption from submitted on the client like this:
Photos = new Mongo.Collection("photos");
Photos.attachSchema(new SimpleSchema({
userId:{
type: String,
autoValue:function(){return this.userId},
},
userName:{
type: String,
autoValue:function(){return Meteor.users.find({_id: this.userId}).username},
},
groupMembers: {
type: String
},
comments: {
type: String
},
fileId: {
type: String
}
}));
I've gotten the code to successfully capture and fill in the userId, as well as the comment and uploaded photo, but I can't seem to get it to capture the username.
It's most likely because you're using find instead of findOne. Since find returns a cursor and not a single document you can't access the username value, because it's not a property of the cursor. If you change it to findOne it should work.
userName:{
type: String,
autoValue:function(){return Meteor.users.findOne({_id: this.userId}).username},
}

Resources