mongoose, how to record update_time in sub docs - node.js

I have a mongoose schema is:
this is my mongoose schema
'use strict';
module.exports = app => {
const mongoose = app.mongoose;
const custSchema = new mongoose.Schema({
belong: { // 所属信息
user_id: { type: 'String', required: true },
type: { type: 'Number', required: true }, // bee、4s店、平台
username: { type: 'String', required: true }, // 用户名
},
delete: { type: Number, default: 0 },
info: { // 客户基本信息
name: { type: 'String', required: true }, // 客户姓名
brith: { type: 'Date', required: true }, // 出生日期
sex: { type: 'Number', required: true }, // 性别
eduction: Number, // 学历
level: { type: 'Number', required: true }, // 客户等级
tag: Number, // 客户标签
tel: { type: 'Number', required: true }, // 电话
family: { // 家庭信息
situation: Number, // 家庭类型
earning: Number, // 家庭总收入
location: { // 家庭住址
province: Number, // 省
city: Number, // 市县
region: Number, // 区镇
addr: String, // 具体地址
},
},
job: { // 工作信息
industry: Number, // 行业
company: String, // 公司
occupation: String, // 职位
earning: Number, // 收入
location: { // 公司地址
province: Number, // 省
city: Number, // 市县
region: Number, // 区镇
addr: String, // 具体地址
},
},
comment: String, // 备注
update_time: { type: 'Date', required: false }, // 数据更新时间
},
... other code
how to save update_time when I update a field in 'custSchema.info'?
such as: I want to update 'info.name', after that, a update_time in 'cust.schema.info' will be included.
I don't prefer to solve this question by add logic on Service, Can I solve it by defining schema?

Yes, you can! Actually, this is a common issue, there are several plugins to help you, my recommendation is: Mongoose Timestamp.
https://github.com/drudge/mongoose-timestamp
It is very simple, a single file, you can actually read it before integrating into you project directly on Github.
Then, you can use the timestamps as follows:
User.findOneAndUpdate({username: 'Prince'}, { password: 'goatcheese' }, { new: true, upsert: true })
.exec(function (err, updated) {
console.log(user.updatedAt); // Should be approximately createdAt + 1 second
console.log(user.createdAt < user.updatedAt); // true
});

Related

How to delete the referenced document in one collection and its record from the referred other collection

In my NodeJS API and MongoDB, I'm trying to delete a record which is a reference to another collection.
What I would like to do is to delete the referred objectId and the records related to the other collection which is referred.
I have 2 models Profiles and Posts and I want to delete the same one post from Profile and Post collection.
I was able to delete the reference id in Profile but I don't know how to delete also the record from Posts collection.
I tried this:
async delete(req, res) {
try {
// Match with username and pull to remove
await Profile.findOneAndUpdate(
{ _id: res.id._id },
{ $pull: { posts: req.params.postId } },
err => {
if (err) {
throw new ErrorHandlers.ErrorHandler(500, err);
}
res.json({ Message: "Deleted" });
}
);
} catch (error) {
res.status(500).send(error);
}
}
And my 2 models:
// Here defining profile model
// Embedded we have the Experience as []
const { Connect } = require("../db");
const { isEmail } = require("validator");
const postSchema = {
type: Connect.Schema.Types.ObjectId,
ref: "Post"
};
const experienceSchema = {
role: {
type: String,
required: true
},
company: {
type: String,
required: true
},
startDate: {
type: Date,
required: true
},
endDate: {
type: Date,
required: false
},
description: {
type: String,
required: false
},
area: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
},
username: {
type: String,
required: false
},
image: {
type: String,
required: false,
default: "https://via.placeholder.com/150"
}
};
const profileSchema = {
firstname: {
type: String,
required: true
},
surname: {
type: String,
required: true
},
email: {
type: String,
trim: true,
lowercase: true,
unique: true,
required: [true, "Email is required"],
validate: {
validator: string => isEmail(string),
message: "Provided email is invalid"
}
},
bio: {
type: String,
required: true
},
title: {
type: String,
required: true
},
area: {
type: String,
required: true
},
imageUrl: {
type: String,
required: false,
default: "https://via.placeholder.com/150"
},
username: {
type: String,
required: true,
unique: true
},
experience: [experienceSchema],
posts: [postSchema],
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
}
};
const collectionName = "profile";
const profileSchemaModel = Connect.Schema(profileSchema);
const Profile = Connect.model(collectionName, profileSchemaModel);
module.exports = Profile;
const { Connect } = require("../db");
const reactionSchema = {
likedBy: {
type: String,
unique: true,
sparse: true
}
};
const postSchema = {
text: {
type: String,
required: true,
unique: true,
sparse: false
},
profile: {
type: Connect.Schema.Types.ObjectId,
ref: "Profile",
},
image: {
type: String,
default: "https://via.placeholder.com/150",
required: false
},
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
},
reactions: [reactionSchema],
comments: {
type: Connect.Schema.Types.ObjectId,
ref: "Comment",
required: false
}
};
const collectionName = "post";
const postSchemaModel = Connect.Schema(postSchema);
const Post = Connect.model(collectionName, postSchemaModel);
module.exports = Post;
Just add a query to remove the post after pulling it's ID from the profile collection:
async delete(req, res) {
try {
// Match with username and pull to remove
await Profile.findOneAndUpdate(
{ _id: res.id._id },
{ $pull: { posts: req.params.postId } },
// You don't need an error callback here since you are
// using async/await. Handle the error in the catch block.
);
await Posts.remove({ _id: req.params.postId });
} catch (error) {
// This is where you handle the error
res.status(500).send(error);
}
}

Node JS and Mongoose How to get data from 2 collections?

I need to get all docs from service collection and it's showing all records when i console content. In content collection there is field mids which is media id and all images are going to media collection. I need to get media url for specific service. But when i console content.mids it returns undefined .Do i need to change in query?
Code is attached for your reference.
// Controller
services: (req, res) => {
Posts.find({content_type:'service'}).then(function(content) {
console.log(content); //right
console.log(content.m_ids); //showing undefined
Media.findById(content.m_ids).then(media => {
res.render('default/services', {content: content, reqUrl: req.url});
});
})
}
Services Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Schema = new Schema({
content_type: {
type: String,
required: true,
maxlength:20
},
content_title: {
type: String,
required: true,
max:100
},
content_url: {
type: String,
required: true,
maxlength:200
},
content_description: {
type: String,
required: true,
},
content_full_description: {
type: String,
required: false,
},
pt_ids: {
type: String,
required: false,
},
pc_ids: {
type: String,
required: false,
},
m_ids: {
type: String,
required: false,
},
created_by_user_id: {
type: String,
default: 1,
},
created_on: {
type: Date,
default: Date.now
},
updated_on: {
type: Date,
default: Date.now
},
post_icon_svg: {
type: String,
required: false,
}
});
module.exports = {Posts: mongoose.model('content_data', PostsSchema )};
// Media Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const MediaSchema = new Schema({
media_name: {
type: String,
required: true
},
media_title: {
type: String,
required: true
},
media_alt: {
type: String,
required: true
},
media_description: {
type: String,
required: false
},
media_url: {
type: String,
required: true,
unique: true
},
created_by_user_id: {
type: String,
default: 1,
},
created_on: {
type: Date,
default: Date.now
},
updated_on: {
type: Date,
default: Date.now
}
});
module.exports = {Media: mongoose.model('media', MediaSchema )};

Get data from mongodb with dynamic nested levels using nodejs and mongoose

For example
I have one table:
Menuid, menuname, parentid, levelid -- this is table
Consider the values:
Menuid:Pg, menuname:mainprogram, programid:'', levelid: 1
Menuid:sb, menuname:subprogram, programid:'Pg', levelid: 2
Menuid:cb, menuname:childprogram, programid:'sb', levelid: 3
Menuid:Pg2, menuname:mainprogram2, programid:'', levelid: 1
Output:
[ {
Menuid:'Pg',
Menuname:'mainprogram',
Children:[ {
Menuid:'sb',
Menuname:'subprogram',
Children:[ {
Menuid:'cb',
Menuname:'childprogram'
} ]
} ]
}, {
Menuid:'Pg2',
Menuname:'mainprogram2'
} ]
getting menu code
exports.getMenus = (req, res, next) => {
// need clarification
}
model for menu
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const menuSchema = mongoose.Schema({
menuId: {
type: String,
required: true,
unique: true
},
menuName: {
type: String,
required: true
},
icon: {
type: String,
required: false
},
type: {
type: String,
required: false
},
url: {
type: String,
required: false
},
levelId: {
type: Number,
required: true
},
programId: {
type: String,
required: false
},
order: {
type: Number,
required: true
},
createdBy: {
type: String,
require: false
},
createdDate: {
type: Date,
require: false,
},
updatedBy: {
type: String,
default: '',
require: false
},
updatedDate: {
type: Date,
default: '',
require: false,
},
});
menuSchema.plugin(uniqueValidator);
module.exports = mongoose.model('Menu', menuSchema);
router:
router.get('/getmenus/:id', MenuController.getMenus);
user request from client like
http://localhost:3000/api/menu/getmenus/pg
getmenus after slash word is a required menus under submenus
Note: if each data has order menans based on menu object need to render with that order. Please provide any solution.
Refer below link
your expected behaviour will be available in this graphlookup
https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/

How to prevent changes from services

I'm using Feathers.js with Mongoose and I want to create a field that cannot be changed by the services.
// account-model.js - A mongoose model
//
// See http://mongoosejs.com/docs/models.html
// for more of what you can do here.
const mongoose = require('mongoose');
require('mongoose-type-email');
module.exports = function(app) {
const mongooseClient = app.get('mongooseClient');
const recovery = new mongooseClient.Schema({
token: { type: String, required: true }
}, {
timestamps: true
});
const account = new mongooseClient.Schema({
firstName: { type: String, required: true },
surname: { type: String, require: true },
phone: { type: String, require: true },
email: { type: mongoose.SchemaTypes.Email, required: true, unique: true },
birth: { type: Date, required: true },
gender: { type: String, required: true },
country: { type: String, required: true },
address: { type: String, required: true },
address2: { type: String, required: false },
city: { type: String, required: true },
postcode: { type: String, required: true },
password: { type: String, required: true },
status: { type: String, required true }
}, {
timestamps: true
});
return mongooseClient.model('account', account);
};
No one can make a post at /account/<id> and change the field status.
This field should only be changed when internally. When some approval service request.
How can I implement this behavior?
This is a perfect use case for Feathers hooks. When accessed externally, in a service method call params.provider will be set so you can check for it and remove the field from data if it is:
module.exports = function() {
return async context => {
if(context.params.provider) {
delete context.data.status;
}
}
}
This hook will be a before hook for the create, update and patch method.

$inc not working for my mongo database (on localhost)

This should be a simple problem. I've formatted my 'update' exactly how it is on mongo's documentation, as you can see:
Message.update(
{ id: messageID },
{ $inc: { votes: 1 } }
);
I am trying to increase 'votes' by 1. Yet it is not changing. Here is my schema file:
var mongoose = require('mongoose');
var MessageSchema = new mongoose.Schema({
room: {
type: String,
required: true
},
timestamp: {
type: Object,
required: true
},
votes: {
type: Number
},
id: {
type: String,
required: true
},
uid: {
type: String,
required: true
},
parent: {
type: String,
required: true
},
text: {
type: String,
required: true
}
});
module.exports = mongoose.model('messages', MessageSchema);
The input 'messageID' is correct, as the 'find' method works perfectly well with this table.
Try with findByIdAndUpdate instead of update . Hope it works
Message.findByIdAndUpdate(messageID ,{ $inc: { votes: 1 }},function(err, response) {
res.send(response);
});

Resources