How can I use date comparison logic for literal with sequelizejs
my database is postgresql
this is my code, but is not working
let order = [
[Sequelize.literal("CASE WHEN 'applyDate' > 'NOW()' THEN 1 ELSE 2 END")],
];
try {
projects = await Project.findAndCountAll({
distinct: true,
where: whereQuery,
order,
include,
limit: keyword ? undefined : limit,
offset,
});
} catch (err) {
console.log(err);
next(err);
return;
}
please help me..
Related
New to MongoDB. I'm trying to add a new document to an existing collection only if a document with the same name does not already exist within that collection. I'm using an if/else statement first to check whether there is a document with the same name as the new entry, and if not, an else statement that will create the new entry. Whatever I try, the new document is not getting added, and instead it returns an empty array. I'd be grateful for any help.
I've tried switching the if/else statements; checking for null and undefined values upon return of if statement
app.post('/cocktails/new', isLoggedIn, (req, res) => {
// add to DB then show item
let name = req.body.name;
let style = req.body.style;
let spirit = req.body.spirit;
let image = req.body.image;
let description = req.body.description;
let newCocktail = {name: name, style: style, base: spirit, image:
image, description: description}
Cocktail.find({name}, function (err, existCocktail) {
if(existCocktail){
console.log(existCocktail)
}
else {Cocktail.create(newCocktail, (err, cocktail) => {
console.log(cocktail)
if (err) {console.log(err)}
else {
res.redirect('/cocktails/' + cocktail._id)}
})
}
})
})
In the event document is not found with the if function, else statements will execute, leading to new document being created with the newCocktail object.
You should use findOne instead of find.
find returns an empty array when no docs found.
The following expression returns true, so your existCocktail condition becomes true, causing your new data not added.
[] ? true : false
Also I refactor your code a bit, you can use destructuring your req.body.
app.post("/cocktails/new", isLoggedIn, (req, res) => {
// add to DB then show item
const { name, style, spirit, image, description } = red.body;
let newCocktail = {
name,
style,
base: spirit,
image,
description
};
Cocktail.findOne({ name }, function(err, existCocktail) {
if (existCocktail) {
console.log(existCocktail);
res.status(400).json({ error: "Name already exists" });
} else {
Cocktail.create(newCocktail, (err, cocktail) => {
console.log(cocktail);
if (err) {
console.log(err);
res.status(500).json({ error: "Something went bad" });
} else {
res.redirect("/cocktails/" + cocktail._id);
}
});
}
});
});
I'm passing the query params and there could be any combination of sort, limit or skip for the Mongoose Query.
What I've thought of is to create mutliple mongoose queries based on what params have been passed. So if only sort is passed then the resulting query will have Document.find({}).sort({}) and incase only limit is passed then query would be Document.find({}).limit({})
Should I write something like this -
router.get('/', (req, res) => {
if(req.query.sortByPrice) {
Property.find({})
.sort({ price: req.query.sortByPrice === 'asc' ? 1 : -1 })
.populate('user_id', 'name')
.exec((err, properties) => {
if (err)
return res
.status(404)
.json({ error: "Can't get user details!" });
res.status(200).json(properties);
});
}
if(req.query.limit) {
Property.find({})
.limit(req.query.limit)
.populate('user_id', 'name')
.exec((err, properties) => {
if (err)
return res
.status(404)
.json({ error: "Can't get user details!" });
res.status(200).json(properties);
});
}
});
You can create a variable options from your request body and pass it as the third argument to the .find() query, no need to write redundant code with if-else block.
Secnd argument to .find() query is projection, so don't forget to pass an empty object there.
Try this :
let options={};
if(req.query.sortByPrice){
options.sort = {
price: req.query.sortByPrice === 'asc' ? 1 : -1
}
}
if(req.query.limit){
options.limit = req.query.limit
}
Property.find({},{},options)
.populate('user_id', 'name')
.exec((err, properties) => {
if (err)
return res
.status(404)
.json({ error: "Can't get user details!" });
res.status(200).json(properties);
return;
});
Note: Dont forget to return after res.status().json(), otherwise you might get error cant set headers after they are sent . if you try to send response again.
I have this loop:
properties.forEach(function(property) {
console.log("property: " + property);
var upsertValues = {};
upsertValues["ID"] = property.ID;
Properties.upsert(upsertValues,
{$set: property},
function(err, nbr) {
if(err)
console.log(err);
else
console.log("upsert successful" + nbr);
});
});
setTimeout(function () {
Fiber(function() {
Meteor.call("removeOldProperties", modification_date);
}).run();
}, 30000)
})
Basically, it updates a bench of documents and at the end, it removes all the once who have not been updated.
I had to use a TimeOut because without that, I removes the documents before their update, as all the Meteor.upsert statements are async.
Is there a better way to do it (without having to use this timeout) ?
Thanks,
Couple thoughts:
upserts are fast, no need for a callback
Fiber is for the server
I don't understand how your upsertValues was a valid query. Is this referring to the document _id? If so, convention is to keep using the name _id, if not, I'd use a more descriptive name. Was this code functioning??
What remains:
var upsertsCompleted = 0;
properties.forEach(function(property) {
Meteor.call("upsertProperties", property, function() {
if (++upsertsCompleted === properties.length) {
Meteor.call("removeOldProperties", modification_date);
}
}
Meteor.methods({
upsertProperties: function (property) {
return Properties.upsert(property.ID, {$set: property});
}
});
I want my data sort by "createdAt" column . Sometime in ascending order and also descending order also. I am using mongo db .
Currently, I have created app which have feature like Users data can be sorted by admin request. Admin can view data in ascending order or by descending order.
I have tried option by using sort parameter which gives me data every time in same order. How can I change as admin per admin request.
Please review below that I have tried.
var options = {
limit: request.body.limit || undefined,
skip: request.body.skip || undefined,
sort: request.body.sort || "createdAt",
where: request.body.where || undefined
};
Users.find(options, function (err, Users) {
if (Users === undefined) {
return response.json({message: "No data Found"});
}
else if (err) {
return response.json({message: err});
} else {
return response.json({data: Users});
}
});
try this
var myQuery = Users.find(options);
// if you want to sort in descending order
myQuery.sort('createdAt DESC');
// if you want to sort in ascending order
myQuery.sort('createdAt ASC')
myQuery.exec(function callBack(err,results){
console.log(results)
});
You have to do something like this:
.sort({ createdAt: 'desc' })
In your case:
var options = {};
options[request.body.sort || "createdAt"] = 'desc'; // or 'asc'
var options = {
limit: request.body.limit || undefined,
skip: request.body.skip || undefined,
sort: request.body.sort || "createdAt desc", // Please mention here, desc or asc followed by space with column name
where: request.body.where || undefined
};
Users.find(options, function (err, Users) {
if (Users === undefined) {
return response.json({message: "No data Found"});
}
else if (err) {
return response.json({message: err});
} else {
return response.json({data: Users});
}
});
Better to use promises. Keep the code simple and easy to understand.
let condition = {
someField: 'value',
someOtherField: 'value'
}
let limit = 10;
let skip = 10;
Users.find(condition)
.limit(limit)
.skip(skip)
.sort({createdAt: 1})
.then(result => {
// do whatever you need to do with the result here
console.log(result)
})
For descending sort, change the sort clause to
.sort({createdAt: 0})
in my case working code below
var posts =Posts.find();
posts.sort('createdAt DESC');
posts.exec(function(err, success) {
if(err) {
res.status(500);
return res.view('500', {data: err});
}
res.json(success)
})
I am in the process of changing the schema for one of my MongoDB collections. (I had been storing dates as strings, and now my application stores them as ISODates; I need to go back and change all of the old records to use ISODates as well.) I think I know how to do this using an update, but since this operation will affect tens of thousands of records I'm hesitant to issue an operation that I'm not 100% sure will work. Is there any way to do a "dry run" of an update that will show me, for a small number of records, the original record and how it would be changed?
Edit: I ended up using the approach of adding a new field to each record, and then (after verifying that the data was right) renaming that field to match the original. It looked like this:
db.events.find({timestamp: {$type: 2}})
.forEach( function (e) {
e.newTimestamp = new ISODate(e.timestamp);
db.events.save(e);
} )
db.events.update({},
{$rename: {'newTimestamp': 'timestamp'}},
{multi: true})
By the way, that method for converting the string times to ISODates was what ended up working. (I got the idea from this SO answer.)
My advice would be to add the ISODate as a new field. Once confirmed that all looks good you could then unset the the string date.
Create a test environment with your database structure. Copy a handful of records to it. Problem solved. Not the solution you were looking for, I'm sure. But, I believe, this is the exact circumstances that a 'test environment' should be used for.
Select ID of particular records that you would like to monitor. place in the update {_id:{$in:[<your monitored id>]}}
Another option which depends of the amount of overhead it will cause you -
You can consider writing a script, that performs the find operation, add printouts or run in debug while the save operation is commented out. Once you've gained confidence you can apply the save operation.
var changesLog = [];
var errorsLog = [];
events.find({timestamp: {$type: 2}}, function (err, events) {
if (err) {
debugger;
throw err;
} else {
for (var i = 0; i < events.length; i++) {
console.log('events' + i +"/"+(candidates.length-1));
var currentEvent = events[i];
var shouldUpdateCandidateData = false;
currentEvent.timestamp = new ISODate(currentEvent.timestamp);
var change = currentEvent._id;
changesLog.push(change);
// // ** Dry Run **
// currentEvent.save(function (err) {
// if (err) {
// debugger;
// errorsLog.push(currentEvent._id + ", " + currentEvent.timeStamp + ', ' + err);
// throw err;
// }
// });
}
console.log('Done');
console.log('Changes:');
console.log(changesLog);
console.log('Errors:');
console.log(errorsLog);
return;
}
});
db.collection.find({"_manager": { $exists: true, $ne: null }}).forEach(
function(doc){
doc['_managers']=[doc._manager]; // String --> List
delete doc['_manager']; // Remove "_managers" key-value pair
printjson(doc); // Debug by output the doc result
//db.teams.save(doc); // Save all the changes into doc data
}
)
In my case the collection contain _manager and I would like to change it to _managers list. I have tested it in my local working as expected.
In the several latest versions of MongoDB (at least starting with 4.2), you could do that using a transaction.
const { MongoClient } = require('mongodb')
async function main({ dryRun }) {
const client = new MongoClient('mongodb://127.0.0.1:27017', {
maxPoolSize: 1
})
const pool = await client.connect()
const db = pool.db('someDB')
const session = pool.startSession()
session.startTransaction()
try {
const filter = { id: 'some-id' }
const update = { $rename: { 'newTimestamp': 'timestamp' } }
// This is the important bit
const options = { session: session }
await db.collection('someCollection').updateMany(
filter,
update,
options // using session
)
const afterUpdate = db.collection('someCollection')
.find(
filter,
options // using session
)
.toArray()
console.debug('updated documents', afterUpdate)
if (dryRun) {
// This will roll back any changes made within the session
await session.abortTransaction()
} else {
await session.commitTransaction()
}
} finally {
await session.endSession()
await pool.close()
}
}
const _ = main({ dryRun: true })