How to save values in column type range in postgres using Sequelize? - node.js

I have a model where I have a column name data_numbers and its type is DataTypes.RANGE(sequelize.INTEGER)
I am using the following line of code to create a new row in table
models.TABLE.create({
data_numbers: ?? //here is what I should write to save a range of numbers.
})

Here you go. While saving data in column type range you have to assign an array of Range type, like following
const TABLE = sequelize.define(
"table",
{
data_numbers: DataTypes.RANGE(sequelize.INTEGER),
},
{
underscored: true,
paranoid: true,
defaultScope: {
attributes: [
"id",
"data_numbers",
],
},
}
);
and while creating new object I added value like following
models.TABLE.create({
data_numbers: [1, 199]
})

Related

Sequelize column reference is ambiguous

I'm trying to accomplish the task of joining all associated models, and then retrieving the count of all the models
I would want the data to be returned as
product {
main_dish: {},
side_dish: {},
drink: {},
purchase_product_count: x,
purchased_products: []
}
I have constructed this in sequelize to try to do this.
await Product.findAll({
include: [{
model: MainCourse,
required: false,
}, {
model: SideDish,
required: false,
}, {
model: Drink,
required: false,
}, {
model: ProductPurchase,
required: false,
where: {
createdAt: {[Op.between]: [two_days_before, current_date]}
},
}],
attributes: {
include: ['*',
[Sequelize.literal(
"(SELECT COUNT(*) from product_purchases as p where p.purchase_product_id = products.product_id)"), "product_purchase_count"],
]
},
offset: 1 * 5,
limit: 5
})
.then((results) => {
console.log(results)
res.status(200).json(results)
})
.catch((err) => {
console.log(err)
res.status(400).json(err)
})
Attempting to run this eager load gives this error
column reference "product_id" is ambiguous
This is the sql generated by sequelize
SELECT "products".*, "main_course"."main_course_id" AS "main_course.main_course_id", "main_course"."type" AS "main_course.type", "main_course"."createdAt" AS "main_course.createdAt", "main_course"."updatedAt" AS "main_course.updatedAt", "main_course"."deletedAt" AS "main_course.deletedAt", "main_course"."main_product_id" AS "main_course.main_product_id", "side_dish"."side_dish_id" AS "side_dish.side_dish_id", "side_dish"."type" AS "side_dish.type", "side_dish"."createdAt" AS "side_dish.createdAt", "side_dish"."updatedAt" AS "side_dish.updatedAt", "side_dish"."deletedAt" AS "side_dish.deletedAt", "side_dish"."side_product_id" AS "side_dish.side_product_id", "drink"."drink_id" AS "drink.drink_id", "drink"."type" AS "drink.type", "drink"."createdAt" AS "drink.createdAt", "drink"."updatedAt" AS "drink.updatedAt", "drink"."deletedAt" AS "drink.deletedAt", "drink"."drink_product_id" AS "drink.drink_product_id", "product_purchases"."product_purchase_id" AS "product_purchases.product_purchase_id", "product_purchases"."price" AS "product_purchases.price", "product_purchases"."quantity" AS "product_purchases.quantity", "product_purchases"."createdAt" AS "product_purchases.createdAt", "product_purchases"."updatedAt" AS "product_purchases.updatedAt", "product_purchases"."deletedAt" AS "product_purchases.deletedAt", "product_purchases"."purchase_product_id" AS "product_purchases.purchase_product_id", "product_purchases"."restaurant_order_id" AS "product_purchases.restaurant_order_id" FROM (SELECT "products"."product_id", "products"."title", "products"."price", "products"."createdAt", "products"."updatedAt", "products"."deletedAt", "products"."restaurant_id", "products".*, (SELECT COUNT(*) from product_purchases as p where p.purchase_product_id = products.product_id) AS "product_purchase_count" FROM "products" AS "products" WHERE ("products"."deletedAt" IS NULL) LIMIT 5 OFFSET 5) AS "products" LEFT OUTER JOIN "main_courses" AS "main_course" ON "products"."product_id" = "main_course"."main_product_id" AND ("main_course"."deletedAt" IS NULL) LEFT OUTER JOIN "side_dishes" AS "side_dish" ON "products"."product_id" = "side_dish"."side_product_id" AND ("side_dish"."deletedAt" IS NULL) LEFT OUTER JOIN "drinks" AS "drink" ON "products"."product_id" = "drink"."drink_product_id" AND ("drink"."deletedAt" IS NULL) LEFT OUTER JOIN "product_purchases" AS "product_purchases" ON "products"."product_id" = "product_purchases"."purchase_product_id" AND ("product_purchases"."deletedAt" IS NULL AND "product_purchases"."createdAt" BETWEEN '2022-05-06 08:35:12.577 +00:00' AND '2022-05-08 08:35:12.577 +00:00');
According to pgadmin the problem starts when doing the join on main_courses
ERROR: column reference "product_id" is ambiguous
LINE 1: ...EFT OUTER JOIN "main_courses" AS "main_course" ON "products"...
I seem to not understand how the sequelize join works as I am using the ORM method of not having any columns be the same. The foreign keys are all different from 'product_id'. Is product_id getting created and joined again on the aggregation possibly? Why am I getting this error, and how can I achieve the result of getting the count of the product_purchases along with the joined array of purchased products.
Obviously I could just get the purchased_products.length and then add it to the object itself, but I'm trying to figure out if you can do it through sequelize without having to hack it in.

Unique key only in array of subschemas?

I have a schemas. One of its keys takes the type of an array of schemas.
let instanceSchema = new Mongoose.Schema({
name: { type: String, required: true, unique: true }
})
let mainSchema = new Mongoose.Schema({
instances: { type: [instanceSchema], required: true }
})
So the mainSchema has a key that is an array of instanceSchemas. I want the behavior to be such that I can have instanceSchemas with the same name if they are members of different mainSchemas, like so:
let MainModel = mongoose.model("MainModel", mainSchema);
// Succeeds
main1 = new MainModel({
"instances": [ {"name": "Instance1"}, {"name": "Instance2"} ];
});
// Succeeds
main2 = new MainModel({
"instances": [ {"name": "Instance1"}, {"name": "Instance2"} ];
});
As shown, we have two named "Instance1" and two named "Instance2" but they are members of different documents (main1 and main2) so my target behavior is that this should be allowed. However, using unique prevents this from happening as Mongoose checks all instanceSchema models. Is there a way to allow duplicates as long as they are members of different documents?
Short answer: no, unique doesn't work like that.
When you tag a field unique in a mongoose schema, it will create a unique index on that field in MongoDB.
MongoDB index entries are made per-document, not per array entry.
For example, if you have an index on {field :1} and insert the document {field:["a","b","a","b","c","d"]}, then the entries in that index for this document will be:
"a"
"b"
"c"
"d"
In MongoDB, when an index is created with the unique: true option, it enforce that any value only appears once #in the index#. This means that the above document would be perfectly acceptable even if the index on {field: 1} were unique.
To quickly demonstrate this, I used your model defined above, and executed:
res1 = await (new MainModel({instances:[{name:"1"},{name:"2"},{name:"1"}]})).save();
console.log("Inserted: ",JSON.stringify(res1));
res2 = await MainModel.collection.getIndexes({full: true});
console.log("Indexes: ",JSON.stringify(res2));
res3 = await (new MainModel({instances:[{name:"3"},{name:"2"},{name:"4"}]})).save();
console.log("Inserted: ",JSON.stringify(res3));
This logged:
Inserted: {"_id":"60d273060ffb1ac8e48359e5","instances":[{"_id":"60d273060ffb1ac8e48359e6","name":"1"},{"_id":"60d273060ffb1ac8e48359e7","name":"2"},{"_id":"60d273060ffb1ac8e48359e8","name":"1"}],"__v":0}
Indexes: [{"v":2,"key":{"_id":1},"name":"_id_"},{"v":2,"unique":true,"key":{"instances.name":1},"name":"instances.name_1","background":true}]
/Users/joe/temp/mongoose/node_modules/mongodb/lib/core/error.js:57
return new MongoError(options);
^
MongoError: E11000 duplicate key error collection: test.mainmodels index: instances.name_1 dup key: { instances.name: "2" }
at Function.create
... snip ... {
driver: true,
index: 0,
code: 11000,
keyPattern: { 'instances.name': 1 },
keyValue: { 'instances.name': '2' }
}
As you can see, it create a unique index on { 'instances.name': 1 }, permitted duplicate entries within a single document, and prohibited an identical entry in the other document.

Insert in sequelize.query and then return the inserted row

Is there a way of returning the inserted row by a raw insert query in sequelize?
The returning option doesn't change anything im the returned value. Is returning the counting of inserted rows and a empty array instead of the inserted rows: [ [], 1 ]
let contato = await sequelize.query(
'INSERT INTO public.contato(nome, telefone, id_empresa, id_status) VALUES ($nome, $telefone, $id_empresa, $id_status);',
{
bind: {
nome: form.nome,
telefone: form.telefone,
id_empresa: filaChat.id_empresa,
id_status: 1,
},
type: QueryTypes.INSERT,
returning: true,
}
);
For postgress, you need RETURNING id included in the raw query.
INSERT INTO public.contato(nome, telefone, id_empresa, id_status)
VALUES ($nome, $telefone, $id_empresa, $id_status)
RETURNING id;

Multiple Select in Tabulator

Is it possible to have one select field depend on the previous one?
Users select one value from select_1 then accordingly the value in select_2 change. Maybe a custom formatter?
const newCol = {//create column group
title: oldRow.title,
field: oldRow.field,
columns: [
{
title: rowData.select1.title, field: rowData.select2.name, editor: 'select',
editorParams: {values: rowData.select1.values}
},
{
title: rowData.select2.title, field: rowData.select2.name, editor: 'select',
editorParams: function (cell) {
console.log(cell)
return {values: [1, 2, 3]}
}
},
],
}
From above I need select1 selected value.
Would this work Editors?:
"If you want to generate the options when the select editor is triggered, then you can pass a function into the editorParams, that must return the option list in one of the two formats outlined above"
{title:"Name", field:"name", editor:"select", editorParams:function(cell){
//create a options list of all values from another column in the table
var rows = table.getRows();
var values = {};
rows.forEach(function(row){
var data = row.getData();
values[data.fullname] = data.fullname;
});
return {values:values};
}
Instead of fetching the all the rows, just fetch the cell value of the previous select column and use that to build the choices for the current select. This sort of depends on the specifics of how the two columns relate to each other. More information on that would be helpful.

Set default value to a new column of a property, mongoose query

I am using node express in a project. I am getting or setting data like
Service.find({ $and:
[{ name: req.body.service },
{ order: req.body.order }]
})
Now I want to add a column in the same table and set a default value. For example, in service table I want to add a column 'deleted' and set it to false for all the current rows. How to do that?
You have to add the column in your model definition and set the default value.
columnName : {
type : String,
default : 'Abcd'
},
// For your case
isDeleted : {
type : Boolean,
default : false
},

Resources