I am using sequelize at nodejs.
When I was making, I set the unique option in a column called 'invoice'.
But since I need to remove the unique option, I have to use migration.
queryInterface.removeConstraint('my_some_table', 'my_constraint');
I saw this command, and I think it is not correct method for me.
How can I remove 'unique option' using migration at sequelize?
invoice: {
type: DataTypes.STRING(50),
unique: true, <<-- I want to remove this.
allowNull: false,
},
This is from the Sequelize documentation and allows you to change the meta data on a column:
queryInterface.changeColumn(
'nameOfAnExistingTable',
'nameOfAnExistingAttribute',
{
type: Sequelize.FLOAT,
allowNull: false,
defaultValue: 0.0
}
)
Related
I have defined my model with minimum_reseller_markup. However, when I query that model, the returned data is not quite what I expected.
Here's my model definition,
SupplierCatalog.init({
supplier_id: DataTypes.INTEGER,
product_variant_id: DataTypes.INTEGER,
product_id: DataTypes.INTEGER,
markup: DataTypes.INTEGER,
minimum_reseller_markup: {
type: DataTypes.INTEGER,
defaultValue: 0
},
status: {
type: DataTypes.BOOLEAN,
defaultValue: true
},
}, {
sequelize,
modelName: 'SupplierCatalog',
});
return SupplierCatalog;
and this is the query result I got from model.dataValues:
{
id: 74982,
supplier_id: 35,
product_variant_id: 80383,
product_id: 7732,
markup: 50000,
minimum_reseller_mark: 45000,
status: false
}
field minimum_reseller_markup got trimmed.
I tried to re-migrate the model but the query result remains the same.
Any idea what might cause this problem?
Overall length of identifiers in PostgreSQL is 63 bytes. So I suppose when Sequelize assigns column aliases for column names it can exceed this limit and you will end up with truncated names like you did with minimum_reseller_markup when you got it without 2 trailing characters.
You can set the option minifyAliases to true while creating Sequelize instance. It helps you to avoid such field truncations:
options.minifyAliases
boolean
default: false
A flag that defines if aliases should be minified (mostly useful to avoid Postgres alias character limit of 64)
See Sequelize instance constructor
and PostgreSQL limits
I'm using sequlize ORM for my Node.js project. Below code is one column in a table.
itemPrice: {
type: DataTypes.DECIMAL,
allowNull: false,
field: 'itemPrice'
},
It is generate the MYSQL DB column as decimal(10,0). It means it cannot save decimal points data. When I'm going to save 12.26, it is save 12. How to create column with saving 2 decimal points.
I tried below code also. It doesn't execute and occurred an error.
itemPrice: {
type: DataTypes.DECIMAL(10,2),
allowNull: false,
field: 'itemPrice'
},
Please show me a direction to do this...
type: DataTypes.DECIMAL(10,2), should work. Once a table is created via sync, it will not be altered even though you have changed your data model definition.
You can use {force: true} in your sync function. Remember that this will drop your table and recreate it.
sequelize.sync({ force: true })
.then(()
I was wondering if there is way to force a unique collection entry but only if entry is not null.
e
Sample schema:
var UsersSchema = new Schema({
name : {type: String, trim: true, index: true, required: true},
email : {type: String, trim: true, index: true, unique: true}
});
'email' in this case is not required but if 'email' is saved I want to make sure that this entry is unique (on a database level).
Empty entries seem to get the value 'null' so every entry wih no email crashes with the 'unique' option (if there is a different user with no email).
Right now I'm solving it on an application level, but would love to save that db query.
thx
As of MongoDB v1.8+ you can get the desired behavior of ensuring unique values but allowing multiple docs without the field by setting the sparse option to true when defining the index. As in:
email : {type: String, trim: true, index: true, unique: true, sparse: true}
Or in the shell:
db.users.ensureIndex({email: 1}, {unique: true, sparse: true});
Note that a unique, sparse index still does not allow multiple docs with an email field with a value of null, only multiple docs without an email field.
See http://docs.mongodb.org/manual/core/index-sparse/
tl;dr
Yes, it is possible to have multiple documents with a field set to null or not defined, while enforcing unique "actual" values.
requirements:
MongoDB v3.2+.
Knowing your concrete value type(s) in advance (e.g, always a string or object when not null).
If you're not interested in the details, feel free to skip to the implementation section.
longer version
To supplement #Nolan's answer, starting with MongoDB v3.2 you can use a partial unique index with a filter expression.
The partial filter expression has limitations. It can only include the following:
equality expressions (i.e. field: value or using the $eq operator),
$exists: true expression,
$gt, $gte, $lt, $lte expressions,
$type expressions,
$and operator at the top-level only
This means that the trivial expression {"yourField"{$ne: null}} cannot be used.
However, assuming that your field always uses the same type, you can use a $type expression.
{ field: { $type: <BSON type number> | <String alias> } }
MongoDB v3.6 added support for specifying multiple possible types, which can be passed as an array:
{ field: { $type: [ <BSON type1> , <BSON type2>, ... ] } }
which means that it allows the value to be of any of a number of multiple types when not null.
Therefore, if we want to allow the email field in the example below to accept either string or, say, binary data values, an appropriate $type expression would be:
{email: {$type: ["string", "binData"]}}
implementation
mongoose
You can specify it in a mongoose schema:
const UsersSchema = new Schema({
name: {type: String, trim: true, index: true, required: true},
email: {
type: String, trim: true, index: {
unique: true,
partialFilterExpression: {email: {$type: "string"}}
}
}
});
or directly add it to the collection (which uses the native node.js driver):
User.collection.createIndex("email", {
unique: true,
partialFilterExpression: {
"email": {
$type: "string"
}
}
});
native mongodb driver
using collection.createIndex
db.collection('users').createIndex({
"email": 1
}, {
unique: true,
partialFilterExpression: {
"email": {
$type: "string"
}
}
},
function (err, results) {
// ...
}
);
mongodb shell
using db.collection.createIndex:
db.users.createIndex({
"email": 1
}, {
unique: true,
partialFilterExpression: {
"email": {$type: "string"}
}
})
This will allow inserting multiple records with a null email, or without an email field at all, but not with the same email string.
Just a quick update to those researching this topic.
The selected answer will work, but you might want to consider using partial indexes instead.
Changed in version 3.2: Starting in MongoDB 3.2, MongoDB provides the
option to create partial indexes. Partial indexes offer a superset of
the functionality of sparse indexes. If you are using MongoDB 3.2 or
later, partial indexes should be preferred over sparse indexes.
More doco on partial indexes: https://docs.mongodb.com/manual/core/index-partial/
Actually, only first document where "email" as field does not exist will get save successfully. Subsequent saves where "email" is not present will fail while giving error ( see code snippet below). For the reason look at MongoDB official documentation with respect to Unique Indexes and Missing Keys here at http://www.mongodb.org/display/DOCS/Indexes#Indexes-UniqueIndexes.
// NOTE: Code to executed in mongo console.
db.things.ensureIndex({firstname: 1}, {unique: true});
db.things.save({lastname: "Smith"});
// Next operation will fail because of the unique index on firstname.
db.things.save({lastname: "Jones"});
By definition unique index can only allow one value to be stored only once. If you consider null as one such value it can only be inserted once! You are correct in your approach by ensuring and validating it at application level. That is how it can be done.
You may also like to read this http://www.mongodb.org/display/DOCS/Querying+and+nulls
I'm using sequelizejs with PostgreSQL as ORM in my webapp, I want to use alphanumeric ID instead numeric.How can I do that ?
Is there some way to do it through sequelize?
Or do I want to generate this id separately and then save it into db ?
Thanks for any help.
You can use a UUID as primary key, and set its default value to uuidv1 or v4
http://docs.sequelizejs.com/en/latest/api/datatypes/#uuid
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
}
I'm using Sails.js (0.9.8) and MongoDB (via the sails-mongo adaptor) to create a collection of pages that can be positioned in a tree-view. I would like to store the path of a page in an array of UUIDs
My model:
module.exports = {
schema: true,
attributes: {
uuid: {
type: 'string',
unique: true,
required: true,
uuidv4: true
},
name: {
type: 'string',
required: true,
empty: false
},
path: {
type: 'array',
required: true,
array: true
}
}
}
It works well when I save a 'root' page (the 'path' property has just one item because it's a root page. Here is what it was saved in MongoDB:
{
_id: ObjectId("52f853e9609fb6c0341bdfcc"),
createdAt: ISODate("2014-02-10T04:22:01.828Z"),
name: "Home Page",
path: [
"a2b23e1f-954b-49a3-91f1-4d62d209a093"
],
updatedAt: ISODate("2014-02-10T04:22:01.833Z"),
uuid: "a2b23e1f-954b-49a3-91f1-4d62d209a093"
}
But when I want to create a 'subpage' below my previous created page (Home Page/Products), I get this error:
MongoError: E11000 duplicate key error index: cms-project.item.$path_1
dup key: { : "a2b23e1f-954b-49a3-91f1-4d62d209a093" }
Here is the data I sent:
{ name: 'Products',
uuid: 'a004ee54-7e42-49bf-976c-9bb93c118038',
path:
[ 'a2b23e1f-954b-49a3-91f1-4d62d209a093',
'a004ee54-7e42-49bf-976c-9bb93c118038' ] }
I probably missed something but I don't know what.
If I store the path in a string instead of an array, it work well, but I find it much less elegant and handy.
Not sure of all the Sails / Waterline parts myself as I've never played with it. But by the error the problem is there is a unique index on your array field.
When you are inserting your second document, you already have one of the values (the parent) in your path field in another document. The unique constraint is not going to allow this. Most certainly for what you are modelling, you do not want this and the index cannot be unique.
I hope that you set this up yourself under the assumption that it meant unique within the array contained in the document. If you did then you know where to look and what to change now. If this is being automatically deployed somehow, then I'm not the one to help.
Change the index to not be unique. You can confirm this through the mongo shell:
use cms-project
db.item.getIndices()
Good luck