问题
I'm having problems with inserting into mongoDB because good objects don't pass the mongoDB validator.
To make it worse, the error is a generic: Document failed validation
which in a big multi-nested object can make things confusing regarding where exactly this validation fails.
myValidatorIs =
{ validator:
{ $jsonSchema :
{ bsonType: "object"
, required: [ "price" ]
, properties:
{ price:
{ bsonType: "double" // price needs to be a double, tried with decimal also.
, description: "must be a double/float and is required"
}
}
}
}
, validationAction: "error"
, validationLevel: "strict"
};
db.collection("collection").insertOne({ price : 4.5 }); // this works
db.collection("collection").insertOne({ price : 4.0 }); // this doesn't - see error below
ERROR: UnhandledPromiseRejectionWarning: MongoError: Document failed validation
My app needs something different but i simplified it here by using price
.
Now after lots of trial and error i figured out what actually happens. Was not as clear as above.
Basically in javascript the 4.0
(float
) is implicitly transformed to 4
(integer
)
And this integer
fails the validation since is not a float
. Which is super wired. Since this data comes from outside, i can't control if is float
or integer
. Javascript only knows about number
.
Is this indeed the problem? I mean i tried lots of different things and i can't see any other reason other then this implicit type conversion.
Because in the validator - if i set bsonType : "int"
and i give it {price: 1}
or {price: 4.0}
then the insertion works with no errors.
How to deal with this type of issue? How to insert {price: 4.0}
?
Also what settings should i include to make that description
field i set to appear in the error message? After all what is the purpose of properties.price.description
if not to create better error messages ?
回答1:
Found 2 solutions:
1. A somewhat wired approach - because i endup with mixed types
in my column. In general, you might not want mixed types since adds complexity - and there is no good reason for them to be considered mixed in my case.
Basically instead of a single type, you can use a list of types like so:
bsonType: "double"
vs bsonType: [ "double", "int" ]
.
This feature is documented here: $types.
myValidatorIs =
{ validator:
{ $jsonSchema :
{ bsonType: "object"
, required: [ "price" ]
, properties:
{ price:
{ bsonType: [ "double", "int" ] // add "int" in this array here
, description: "must be a double/float and is required"
}
}
}
}
, validationAction: "error"
, validationLevel: "strict"
};
2. The recommended approach, found this with help from @lvrf
const MongoType_Double = require('mongodb').Double;
myValidatorIs =
{ validator:
{ $jsonSchema :
{ bsonType: "object"
, required: [ "price" ]
, properties:
{ price:
{ bsonType: "double" // leave this as double
, description: "must be a double/float and is required"
}
}
}
}
, validationAction: "error"
, validationLevel: "strict"
};
// then use the MongoType_Double constructor like so:
db.collection("collection").insertOne({ price : MongoType_Double(4.0) }); // no errors..
This should also work for all the other types like timestamp
and such:
来源:https://stackoverflow.com/questions/57810998/mongoerror-document-failed-validation-how-to-insert-both-float-and-int-into-t