Grails 3 and GORM 6 for MongoDB - duplicated key error - mongodb

Environment:
Grails 3.2.9
GORM 6.1.2 for MongoDB 3.4.2
This is my (simplified) domain class
class Cluster {
String name
String slug
static constraints = {
name blank: false, unique: true
slug blank: false, unique: true, validator: { return it == it.toLowerCase().replaceAll(/[^\w-]/, '') }
}
static mapping = {
collection 'Cluster'
id name: 'slug'
}
}
As you can see I mapped the slug property to be the document _id.
I can successfully add a document with
Cluster cluster = new Cluster(name: 'Dallas', slug: 'dal05')
cluster.insert(failOnError: true)
and everything works fine. But if I execute the same insert command again I get a duplicated key exception:
com.mongodb.MongoBulkWriteException: Bulk write operation error on server localhost:27017. Write errors: [BulkWriteError{index=0, code=11000, message='E11000 duplicate key error index: db.Cluster.$_id_ dup key: { : "dal05" }', details={ }}]
while I would have expected a simple validation error, stating duplicated key.
However, although the unique constraint fails, validation is correctly triggered for the other two (empty value or e.g. 'Dal05' -capital letters not allowed-).
Without mapping the id on slug property, so leaving the default assigned logic, everything works as expected.
Am I missing something? Thanks in advance!

It seems this is actually a bug, scheduled to be fixed in upcoming GORM release 6.1.5.
Ref. issue: https://github.com/grails/grails-data-mapping/issues/951

Related

Meteor Upsert Syntax with Nested Values

I am having trouble trying to get a Collection.upsert to work in Meteor 1.4.3.2.
My app pulls in active listings from eBay and inserts them into the database if they don't already exist, otherwise it updates the listing that is already stored. So, what I am trying is the following in a meteor method:
let upsertObj = {$set: {}};
const account = ListingAccounts.findOne( ... );
if (!account) // throw an error because account info is required by schema
upsertObj.$set['account.id'] = account._id;
upsertObj.$set['account.username'] = account.username;
upsertObj.$set['account.nickname'] = account.nickname;
// ... also gets other listing data such as listingId, title, condition, etc...
return Listings.upsert({listingId: eBayListingID}, upsertObj);
There are other values that are nested similarly to the account details above, and they all seem to work. I've logged the final upsertObj object and the values are valid and comply with my schema (SimpleSchema), but just for good measure, here is an excerpt of the final upsert object I am logging on the server just before the upsert happens:
{ '$set':
{ 'account.id': 'trustmethisisvalidstring',
'account.username': 'ValidAccountNameString',
'account.nickname': 'ValidAccountNicknameString',
/* more name:values below this */
}
}
Here is an excerpt from my schema (aldeed:simple-schema 1.5.3)
ListingsSchema = new SimpleSchema({
account: {
type: Object
},
"account.id": {
type: String,
optional: true // added after question asked
},
"account.username": {
type: String,
optional: true // added after question asked
},
"account.nickname": {
type: String,
optional: true // was always optional
},
...
});
I am receiving the error on the client with the following details:
[{"name":"account.id","type":"required","value":null},{"name":"account.username","type":"required","value":null}]
with the reason reason: "Id is required"
This is the first time I've tried using upsert and I can't help but feel I am missing the mark on something. Maybe my syntax is off, or maybe I'm just not using bracket notation correctly? I don't know, the Meteor docs unfortunately do not have any examples that I could find.
Any assistance or clarification on using Upsert would be super appreciated, thank you!

Duplicate Key Error on MongoDB Model, Even When Model is Not Enforcing Uniqueness for that Value

In my app I have an endpoint that allows a user to create a new document by simply passing something like this:
{ name: { long: "some name" } }
Now, the relevant portion of the model for this document looks like this:
name: {
long: {
type: String,
trim: true
},
short: {
type: String,
trim: true
}
}
As you can see, I don't have "short" set to "unique: true". However, the user is getting this error:
"errmsg": "E11000 duplicate key error collection: hr.agencies index: name.short_1 dup key: { : null }"
So, clearly the problem here is that once you have more than one "name.short" with a value of null, its producing a dupe error. However, since I don't have unique set to true in the model, I'm not sure why it's enforcing this as a rule.
What could the issue be here, and how can I resolve it? Is there a way I can explicitly say, don't enforce uniqueness on this field?
Try to remove the index from the short key using
db.collection.dropIndex({ "name.short": 1 })

Model validation isUUID not working

I am currently trying to implement usage of UUID as s primary key for my user model in SailsJS application, using MongoDB. As for now the primary key is generated by other system, I would like to validate if uuid attribute is valid UUID.
Validation isEmail is working fine for me, but isUUID accepts string like "john-doe" so it looks like it is not working.
My configuration looks like this:
module.exports = {
primaryKey: 'uuid',
dontUseObjectIds: true,
attributes: {
uuid: {
type: 'string',
isUUID: true,
columnName: '_id',
required: true
},
...
}
}
My only thought is that the validaiton does not work against primary key attribute.
Any ideas what else might be wrong? Thanks

Got duplicate key error dup key: { : undefined }

I have an array field called udids in Meteor.users schema, which should contains unique elements. This is how I defined the index using SimpleSchema and Collection2:
new SimpleSchema({
...
udids: {
type: Array,
index: true,
unique: true,
optional: true,
sparse: true,
},
'udids.$': {
type: String,
},
...
})
However, when I start the app, I got this error: E11000 duplicate key error collection: meteor.users index: c2_udids dup key: { : undefined }.
I tried searching for the documents with udids = undefined in the database: db.users.find({ udids: { $type: 6 } }) ($type: 6 for undefined value) but it returns nothing.
The error message is a bit unclear so I had to guess the reason why. I found out that the current database already has some users with udids = []. I'm writing a migration script to unset this field from those users. Hopefully this will help others who have the same problem as me.
I've not tested this, but it should ideally work.
Used Meteor.users as a collection name. You may want to replace it with whichever collection you want to run the validation against.
Made use of custom function to find at least one doc which contains the field's value in udids.
If you don't have access to the collection on the client side, then you can edit the custom function and have it handled asynchronously.
new SimpleSchema({
...
'udids': {
optional: true,
type: [String], // an array of string eg. ['A','B']
custom: function() {
// this.value = current field's value
// Below mongo query will check to see if there is at least one
// mongo doc whose udids contains the currently entered field's value.
// if found, then return the error message.
if (Meteor.users.findOne({
udids: {
$in: [this.value]
}
})) {
return "duplicateMsg";
}
},
...
});
SimpleSchema.messages({ duplicateMsg:"Udid already exists"});

MongoDB - Duplicate Key Error After Changing Model To Allow Duplicates

I am using the mean stack. In Mongoose I defined a model with these properties:
var personSchema = new mongoose.Schema({
personName:{ type: String, unique: true, required: true, index:true },
start: { type: Date},
end: { type: Date }
});
However, when testing I realised I had made a mistake and that personName should not be unique. I removed the unique: true property and restarted MongoDB and the app.
However, I still get the duplicate key error when submitting.
Can anyone tell me what I'm doing wrong?
You might have created an index for the personName field.
Remove the index associated with field personName and try, it will work.
Reason:
when the field personName in the state "unique: true" index would be fine and now after removal of the state "unique: true". If we are trying to enter a record which is having a personName which is already there in the DB, then DB will throw Duplicate key error.