I'm writing my service to update a row using sequelize for PostGres. When I try out my query using a PSequel it works fine:
UPDATE "test_table" SET "test_col"=NULL WHERE "id"= '2'
But using sequelize it throws a 500 error:
db.TestTable.update({ testCol: NULL }, { where: { id: id } })
.then((count) => {
if (count) {
return count;
}
});
My model does allowNull which I believe is what allows null values to be the default as well as set:
testCol: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
field: 'test_col'
},
Any other value but NULL works as expected. Is there a different method for setting null values?
From the looks of it, I think your issue is that you are using SQL's syntax for a null value ('NULL') where you should be using JS syntax ('null').
db.TestTable.update({ testCol: null }, { where: { id: id } })
.then((count) => {
if (count) {
return count;
}
});
should work.
Have you checked a more detailed error message in logs? I'd suggest you to add a promise catching error and then update your question.
For now, my guess is that you created your connection with omitNull: true. Call an update function with just one null property probably is the reason of error 500 because it'll generate a incomplete UPDATE command (without SET).
Try to set omitNull: false or, if you cannot do this test, try to update this way:
db.TestTable.testCol = null;
db.TestTable.save(['testCol']);
More info here.
Related
I am using prisma with mongoDb for the first time and I want to update a boolean value stored in a collection, but I am not able to find a way/query to update the value from true to false or vise versa...:(
const updateUser = await prisma.user.update({
where: {
userToken: token,
},
data: {
isOnline: true,
},
})
I have this 'isOnline' stored as false default and this is what I have tried wrt prisma official documentation, but this did not worked for me
I think you are looking for set
const updateUser = await prisma.user.update({
where: {
userToken: token,
},
data: {
isOnline: {
set: true
},
},
})
Since true and false values could be mistaken as a special instruction in "prisma logics", the response from #Fastnligth should be the correct one -did't tried that though-.
Since Prisma ORM implemented MongoDB as an after thought, some of these functionalities might "seem a bit off".
I've arrived here trying to update an embedded field without updating the whole document, just the given field.
Leaving my two cents in case somebody else is having the same sailing over google ⛵️
You can do that as follows
const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
shippingAddress: {
// Update just the zip field
update: {
zip: '41232',
},
},
},
})
official docs: https://www.prisma.io/docs/concepts/components/prisma-client/composite-types
I’m having trouble with upsert with meteor.js. I could update questions finely with the below codes but I won’t be able to insert new data.
file in client side
const onSave = () =>{
// there is more codes but omitted
questions.forEach(question => {
Meteor.call('modifyQuestion', question);
})
}
file in server side (collection file)
modifyQuestion(question) {
check(question, Object);
const questionId = Measures.findOne({questionId: question._id});
Measures.upsert(
{_id: questionId._id},
{
$set: {
title: question.text,
},
},
);
},
Got error saying…
Exception while simulating the effect of invoking 'modifyQuestion' TypeError: Cannot read properties of undefined (reading '_id')
I thought when {_id: questionId._id} got undefined, that’s the time upsert understand that there is no matching data found and insert one as new data into the database.
Is this wrong?
I switched $set to $setOnInsert, but still didn't work...
ADDED
Now I don't see any error but i couldn't insert new data. I could update data tho.
modifyQuestion(question) {
check(question, Object);
Measures.upsert(
{questionId: question._id}, // changed
{
$set: {
title: question.text,
},
$setOnInsert: {type: 'multipleChoice'}
},
);
},
Also removed const questionId = Measures..... part
You still need to set the questionId on insert:
modifyQuestion(question) {
check(question, Object);
Measures.upsert(
{ questionId: question._id },
{
$set: {
title: question.text,
},
$setOnInsert: {
questionId: question._id
type: 'multipleChoice'
}
},
);
},
Otherwise there will never be a doc that contains the questionId.
Note: Another helpful tool would be Collection2 and define a schema, so it throws errors, in case docs are inserted/updated that violate a schema. Using this would have thrown, that questionId is missing on insert.
I have tried dozens of solutions, and none of these worked and most of them are deprecated.
I have a collection with documents like this:
_id: 5d99ef3285c93711828cd15d
code: 1234
name: "Foo"
surname: "Bar"
address: "That street"
phone: 1234567
I would like to insert new document only if there isn't any document with the same code.
My last try was this:
const result = await db.collection('users').findOneAndUpdate(
{ code: user.code },
{
$setOnInsert: user,
},
{
upsert: true,
}
);
but I get E11000 duplicate key error collection...
updateOne() returns the same error; update() is deprecated...
So, how to add only new document and get the result (true if document has been added or false if it already exists)?
Thank you.
As far as my knowledge is,
with $set and $setOnInsert, we can not update/insert the same field.
i.e. $set and $setOnInsert should be mutually exclusive.
It works if the document is being updated, but throws an exception if document is being inserted.
In case of update, $setOnInsert will be ignored.
In case of insertion, both will be executed.
I think the solution would be,
use returnNewDocument and have one field in the schema isUpdated defaults to false.
Note:
make sure whenever you use "insert" operation on the collection, you don't add isUpdated which will be set to false then or set it to false.
form a query like
db.collection('users').findOneAndUpdate(
{ code: user.code },
{
$set: user, // which has user.isUpdated set to true
},
{
upsert: true,
returnNewDocument: false, // (by default it is false only)
}
);
With this logic,
So let's go step by step,
If the document doc1 is not present, it will be inserted, and mongo will return the response null. You will know, it is Inserted.
If the document doc2 is present(considering this logic is not applied on the previously inserted document doc2 before and isUpdated field is not present in doc2), it will execute $set so in returned cursor, this field not present i.e. undefined, so you know from this, it is updated.
let's say we fire the same query for doc1 again (which is present and we have applied our new logic), then there are two cases
a. it will be updated and in the cursor, we have isUpdated equal to false.
b. it will be updated and in the cursor, we have isUpdated equal to true.
In both case you know it is Updated
I think this approach should solve your problem.
Please share if this helps you, or you find any other solution.
UPDATE
ACTUALLY
You dont even need another field isUpdated, without this fiels this should work with the same logic.
i.e. If cursor is null then its inserted, if not null then its updated.
You can still run a query like this;
document = db.collection('users').findOne({code:userCode});
if(document == null){
//document doesn't exists so you can use insertOne
}
else{
// document exists, sou you can update
}
it won't be efficient but it'll do the work.
You can simply wrap the request with a try/catch block to catch the Error. Then return false when this exception occured.
You could use findOne to see if a user with that code exists first
const result = await db.collection('users')
.findOne({ code: user.code });
if( result ){
return res
.status(400)
.json({ errors: [{ msg: 'User already exists' }] });
}
//create
user = new User({
code = code,
name = name,
foo = foo
)}
//save
user.save();
res.json(user);
Try this one
db.collection("users").findOne({ code: user.code }, (err, data) => {
if (data) {
return res.send(false);
} else {
// a document
var user = new User({
code: code,
name: "Foo",
surname: "Bar",
address: "That street",
phone: 1234568
});
// save model to database
user.save(function(err, book) {
if (err) return console.error(err);
return res.send(true);
});
}
});
Users.findOneAndUpdate({code:user.code}, {upsert: true, new: true, setDefaultsOnInsert: true }, function(error, result) { if (error) return; // do something with the document }).
I think it would work. Let us know if you have any questions.
I attempted to create a model in sequelize (say has 3 attributes, attrA, B, and C) with some custom validation logic. This tutorial helped me get most of it set up:
const Model = Sequelize.define('model', {
attrA: { type: Sequelize.STRING },
attrB: { type: Sequelize.STRING },
attrC: { type: Sequelize.STRING },
}, {
validate: {
someValidationLogic() {
// Do something with attrA,B,C
// if (this.attrA ... this.attrB ... this.attrC) throw new Error..
}
}
})
In the application logic however, only say, 2 out of the 3 attributes (A and B) need to be updated:
Model.update(
{
attrA: 'foo',
attrB: 'bar'
}, {
where: {
id: 1,
},
returning: true,
})
This results in that when the custom validation logic being called, in the this object accessed in the function, only attrA and attrB are defined in this, and attrC remained undefined. This causes the validation logic to fail because attrC cannot be read. Is there any way I can get the object visible from someValidationLogic() to have all attributes populated? Or should this "validation" shouldn't have been validation logic at all and should've been done on the application level?
Your validation logic could take in account the possibility of attrC not being defined :
validate: {
someValidationLogic() {
if (this.attrA !== 'undefined' && this.attrA === 'forbidden value' ) {
// throw new Error
}
}
}
But if your validation includes checking the provided values against current database values, then you would better handle this in the application layer : first recover the current database record, manipulate it as needed, then save it to database.
var query = mycouchbase.view('doc', 'myview');
query.query({
limit: 1
}, function(err, results) {
for (i in results) console.log(results[i]);
});
in couchbase admin console what I saw is
but in javascript console
console - { id: '1NR10', key: '1NR10', value: null }
value always is null
your comment welcome
I think by default "IncludeDocs" is false, so you will need to explicitly set IncludeDocs: true (please check exacte syntax in the documentation)