I am trying to make this basic CRM and here i need to see how many times the link has been visited by the client! is there any way i can do that and store ?
Actually I did this, as Ravi Teja said comment.
Added userClicks in the database model in case of mongoose.
(This is nested into another object)
analytics: {
userClicks: {
type: Number,
default : 0
}
}
When any request hits to that URL, I just update that count by one.
app.get('URL', (req, res) => {
//First find document in database
Url.findOne({
$text: {
$search: request.params.shortUrl
}
}).then(url => {
if (url === null) {
return response.status(404).json({
message: "Link in not valid"
});
} else {
//If successfully found, get already stored value and updated with +1, and then update that document.
const _id = url._id
let counterClicks = url.analytics.userClicks;
//Update existing values
counterClicks++;
Url.findByIdAndUpdate({
_id
}, {
$set: {
'analytics.userClicks': counterClicks
}
}).exec().then(url => {
console.log(url);
return response.redirect(302, url.originalUrl);
}).catch(error => {
console.log(error);
});
}
}).catch(error => {
console.log(error);
});
});
You can do this by newer async-await syntax.
From the above's code snippet, we will get idea, How to implement it.
Related
I am write API in expressjs with Sequence. But I got problem with return value when update!
I follow a tutorial on internet but it got error when num=[1] not num=1 although updating success!
exports.update = (req, res) => {
const { id } = req.params;
Post.update(req.body, {
where: { id }
})
.then((num) => {
if (num === 1) {
res.send({
message: 'Post was updated successfully.'
});
}
else {
res.send({
message: `Cannot update Post with id=${id}. Maybe Post was not found or req.body is empty!`
});
}
})
.catch((err) => {
res.status(500).send({
message: `Error updating Post with id=${id}`
});
});
};
So, what return value after call update method? and how do I solve it? Thanks.
The sequelize document of update is
public static async update(values: object, options: object): Promise<Array<number, number>>
Promise<Array<number, number>>
The promise returns an array with one or two elements. The first element is always the number of affected rows, while the second element is the actual affected rows (only supported in postgres with options.returning true).
So, it will not return only the number. you need to follow the document.
To resolve
.then((nums) => {
const num = nums[0]
.....
I'm currently implementing admin dashboard of online shopping app.I want to implement method to perform user deletion and store that deleted user data temporally on another collection.
(Copy_userdata->Save it on another collection -> delete original data)
As an example my users data currently available in collection called users, and after deleting that user particular user's data must be available in another collection, lets say deleted_users collection. Are there any easy way to do that? thanks!
You will be modify some of the code but this is the basic logic,
Use aggregation for copy collections over
Refer here for aggregate function using mongo client
So the function looks like this
public aggregation(collectionName: string, pipelines: Object[]): Promise<Array<any>>
{
return new Promise((resolve, reject) =>
{
let cursor: mongodb.AggregationCursor<any> = null;
//Here you will use getCollection method on your own to fetch the collection
this.getCollection(collectionName)
.then((collection: mongodb.Collection) =>
{
cursor = collection.aggregate(pipelines);
return cursor.toArray();
})
.then((result: Array<any>) =>
{
return resolve(result);
})
.catch((error: any) =>
{
//error//
});
}
public dropCollection(collectionName: string): Promise<any>
{
return new Promise((resolve, reject) =>
{
this.getCollection(collectionName)
.then((collection: mongodb.Collection) =>
{
collection.drop((err: Error, result: any) =>
{
if (err)
{
return reject(DataDropError);
}
return resolve(result);
});
})
.catch(reject);
});
}
public async backupAndDrop()
{
const Object = [ { $match: {} }, { $out: "DeletedCollection" } ];
try
{
await this.aggregationPipeline("originalCollection", Object);
await this.dropCollection("originalCollection");
}
catch (e)
{
throw e;
}
}
Also try to run this on your mongo shell:
db.originalCollection.aggregate([ { $match: {} }, { $out: "Backup" } ])
Why don't you add a flag like isDeleted which is false by default and then make it true when the user is deleted?
You can do something like this...
Client.connect(connection_string, function(err, db) {
if(err){
console.log(err);
}
else{
db.collection(CollectionA).find().forEach(function(d){ db.collection(CollectionB).insert(d); });
}
Try out if it works.
This can help too:
How to properly reuse connection to Mongodb across NodeJs application and modules
You can first find the record to be deleted and do a create with that data to the new collection and then delete the record.
db.collection(CollectionA).findOne({userIdTODelete}, function(err, res){
db.collection(CollectionB).insertOne(res, function() {
db.collection(CollectionA).deleteOne({userIdTODelete});
})
});
I'm writing the backend for creating audit protocols. The user should be able to create criterias for the audit protocol. For this, i have the following backend-method to make sure, the protocol gets only created completely or the process of creating is canceled. It is possible to set several kinds of forms / criterias. But it could be, that only one kind of form is required. I do check that with the if-statement.
The creating works as expected. But the REST API always returns null to the clients. So i can't do further processing on the frontend regarding to the result of the creation process.
Technologies: Node.js and Sequelize. Frontend in angular / ionic. Database in mySQL.
I tried around with some transaction passing and return statements. I tried to compare it to a similiar code snippet, which works as expected.
exports.setAudit = (req, res, next) => {
trueFalseCriteria = req.body.trueFalseForms;
isShouldCriteria = req.body.isShouldForms;
generalCriteria = req.body.generalForms;
measurementCriteria = req.body.measurementForms;
toolId = req.body.toolId;
// Transaction is used to roll the whole transaction back if something wents wrong
return sequelize
.transaction(t => {
return audit
.create(
{
// Creating an audit referencing the tool
toolId: toolId
},
{ transaction: t }
)
.then(
// Getting the id of the audit that we just created
audit => {
return audit.id;
},
{ transaction: t }
)
.then(auditId => {
// Check wether the kind of form is used or not. If so, sequelize tries to do a bulk insert into the databases.
// Each bulk insert throws an error if it fails to cancel the whole transaction
if (trueFalseCriteria) {
console.log(1);
trueFalseCriteria.forEach(dataEl => {
dataEl.auditId = auditId;
});
trueFalseCriterion.bulkCreate(trueFalseCriteria).catch(err => {
// Throw error to cancel transaction
throw new Error(err);
});
}
if (isShouldCriteria) {
console.log(2);
isShouldCriteria.forEach(dataEl => {
dataEl.auditId = auditId;
});
isShouldCriterion.bulkCreate(isShouldCriteria).catch(err => {
// Throw error to cancel transaction
throw new Error(err);
});
}
if (generalCriteria) {
console.log(3);
generalCriteria.forEach(dataEl => {
dataEl.auditId = auditId;
});
generalCriterion.bulkCreate(generalCriteria).catch(err => {
// Throw error to cancel transaction
throw new Error(err);
});
}
if (measurementCriteria) {
console.log(4);
measurementCriteria.forEach(dataEl => {
dataEl.auditId = auditId;
});
measurementCriterion.bulkCreate(measurementCriteria).catch(err => {
// Throw error to cancel transaction
throw new Error(err);
});
}
}, { transaction: t });
})
.then(data => {
console.log(5);
res.status(200).json(data);
})
.catch(err => {
console.log(6);
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
});
};
Expected result: Http response with status code 200 on success
Actual result: null
I think you are missing a return for the last .then():
.then(auditId => {
// Check wether the kind of form is used or not. If so, sequelize tries to do a bulk insert into the databases.
.....
if (measurementCriteria) {
....
}
// RETURN SOMETHING HERE
}, { transaction: t });
I want to know if there is a way to check if a property is present in a Cloud Firestore document. Something like document.contains("property_name") or if there is a document property exist.
To solve this, you can simply check the DocumentSnapshot object for nullity like this:
var yourRef = db.collection('yourCollection').doc('yourDocument');
var getDoc = yourRef.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
if(doc.get('yourPropertyName') != null) {
console.log('Document data:', doc.data());
} else {
console.log('yourPropertyName does not exist!');
}
}
})
.catch(err => {
console.log('Error getting document', err);
});
You could use the in operator like in the snippet bellow
const ref = admin.firestore().collection('yourCollectionName').doc('yourDocName')
try {
const res = await ref.get()
const data = res.data()
if (!res.exists) {
if (!("yourPropertyName" in data)) {
// Do your thing
}
} else {
// Do your other thing
}
} catch (err) {
res.send({err: 'Something went terribly wrong'})
}
I think you refer to making a query.
Still there is no way to check if some field is present or not in the Firestore. But you can add another field with value true/false
val query = refUsersCollection
.whereEqualTo("hasLocation", true)
query.get().addOnSuccessListener {
// use the result
}
check out this links for more
https://firebase.google.com/docs/firestore/query-data/queries
How do I get documents where a specific field exists/does not exists in Firebase Cloud Firestore?
I have a REST API for songs resources, they got an id and a title, admins can perform GET /songs/:id directly, but common users can only access through GET /songs/:title.
So if a common user tries to access to a resource like:
{
"id":9248,
"title": "Hala Madrid"
}
By requesting GET /songs/9248 he should be redirected to GET /songs/hala_madrid.
So I could have two different route handlers, and repeat the query. But I really don't want to query twice. So I thought I could reset url and assign the found song to req.song.
I tried setting up the following routes and implement a single get controller method:
router.get('/:id([0-9]+)', songs.get);
router.get('/:title', songs.get);
function get(req, res, next) {
let { id, title} = req.params;
console.log(id, title);
let permalink = id || title;
let field = isNaN(permalink) ? 'title' : 'id';
if (req.song) {
let { song } = req;
return res.render('app', {song, title: 'song', page: 'song'});
}
queries.getSong(field, permalink).then(result => {
let song = result[0];
if (req.session.user.role === 'user' && field === 'id') {
req.song = song;
req.url = `/songs/${song.title}`;
return next();
}
return res.render('app', {song, title: 'song', page: 'song'});
})
.catch(err => {
console.error(err);
return res.status(500).json({error: err});
});
}
I'm a bit lost as it's ending up in unhandled error, I dont know how reload the request to be handled again.
Maybe I'm misunderstanding something but do you have to have two parameters?
router.get('/songs/:idortitle', function(req,res,next) {
const permalink = req.params.idortitle;
const songQuery !isNaN(permalink) && !req.session.user.role ==='user' ? queries.getSong('id',permalink) :queries.getSong('title',permalink);
songQuery.then(result => {
res.render('app', {song, title: 'song', page: 'song'});
}).catch(e => {
console.error(err);
return res.status(500).json({error: err});
});
});
This case just checks if the parameter is a number and the user is not 'user' (then its admin I assume) and then queries by id. Otherwise it queries by title
so /songs/9248 and /songs/hala_madrid works