I need to find the element by id, then go into the array of objects, find the desired by id and add the field guessId into it and insert the id key into it and assign the array of id. How can I do that ?
https://jsoneditoronline.org/?id=442f1dae0b2d4997ac69d44614e55aa6
In general, I need to create a GuessId field with such a structure
in fact, I am doing the voting, that is, the key in guessId will be go to vote, and the array to it, this is users who vote
{
"_id": "f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"bio": {
"firstname": "Лена",
"lastname": "фыв",
"middlename": "",
"company": "вв"
},
"files": [
{
"_id": "2e4e40c7-4df6-4974-8d16-bb24cd8134d6",
"destination": "./uploads/f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"filename": "2e4e40c7-4df6-4974-8d16-bb24cd8134d6.mp3",
"path": "uploads\\f58482b1-ae3a-4d8a-b53b-ede80fe1e225\\2e4e40c7-4df6-4974-8d16-bb24cd8134d6.mp3",
"folder": "f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"info": {
"size": 20805727,
"mimetype": "audio/mp3",
"encoding": "7bit",
"originalname": "Ахуевший Ленусик (Банк русский стандарт). Выпуск #5..mp3",
"fieldname": "selectedFile"
},
"userId": "5e05da745b21e61ccc84a892",
"date": "2019-12-27T10:19:12.213Z"
},
{
"_id": "81b94dea-ece6-421c-b68a-0aa59332cd0d",
"destination": "./uploads/f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"filename": "81b94dea-ece6-421c-b68a-0aa59332cd0d.mp3",
"path": "uploads\\f58482b1-ae3a-4d8a-b53b-ede80fe1e225\\81b94dea-ece6-421c-b68a-0aa59332cd0d.mp3",
"folder": "f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"info": {
"size": 13515683,
"mimetype": "audio/mp3",
"encoding": "7bit",
"originalname": "Выпуск #75 Попрошайка НСВ..mp3",
"fieldname": "selectedFile"
},
"userId": "5e05da745b21e61ccc84a892",
"date": "2019-12-27T10:25:37.710Z"
}
],
"date": "2019-12-27T10:19:12.213Z",
"__v": 1
}
Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const HabalkaSchema = new Schema({
_id: {
type: String
},
bio: {
firstname: String,
lastname: String,
middlename: String,
company: String
},
files: [
{
_id: {
type: String
},
destination: {
type: String
},
filename: {
type: String
},
path: {
type: String
},
folder: {
type: String
},
info: {
size: {
type: Number
},
mimetype: {
type: String
},
encoding: {
type: String
},
originalname: {
type: String
},
fieldname: {
type: String
},
},
date: {
type: Date,
default: Date.now
},
bio: {
type: Object
},
userId: String,
guessId: {},
}
],
date: {
type: Date,
default: Date.now
}
});
module.exports = Habalka = mongoose.model('habalka', HabalkaSchema);
You can use the positional $ operator like this:
router.put("/habalka/:id/:fileId/:guessId", async (req, res) => {
const result = await Habalka.findOneAndUpdate(
{
_id: req.params.id,
"files._id": req.params.fileId
},
{
"files.$.guessId": {
[req.params.guessId]: ["a", "b"] //todo: get this array from req.body
}
},
{
new: true
}
);
res.send(result);
});
Route url: http://..../habalka/f58482b1-ae3a-4d8a-b53b-ede80fe1e225/2e4e40c7-4df6-4974-8d16-bb24cd8134d6/asda2
This will give you a result like this in the given file:
"files": [
{
"info": {
"size": 20805727,
"mimetype": "audio/mp3",
"encoding": "7bit",
"originalname": "Ахуевший Ленусик (Банк русский стандарт). Выпуск #5..mp3",
"fieldname": "selectedFile"
},
"date": "2019-12-27T10:19:12.213Z",
"_id": "2e4e40c7-4df6-4974-8d16-bb24cd8134d6",
"destination": "./uploads/f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"filename": "2e4e40c7-4df6-4974-8d16-bb24cd8134d6.mp3",
"path": "uploads\\f58482b1-ae3a-4d8a-b53b-ede80fe1e225\\2e4e40c7-4df6-4974-8d16-bb24cd8134d6.mp3",
"folder": "f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"userId": "5e05da745b21e61ccc84a892",
"guessId": {
"asda2": [
"a",
"b"
]
}
},
And later if you want to add an item inside one of the guessId arrays, you can use the following code:
router.put("/habalka/:id/:fileId/:guessId", async (req, res) => {
const result = await Habalka.findOneAndUpdate(
{
_id: req.params.id,
"files._id": req.params.fileId
},
{ $push: { [`files.$.guessId.${req.params.guessId}`]: "c" } },
{
new: true
}
);
res.send(result);
});
Related
I'm trying to get an object which has isDraft value true, but I'm also getting objects which have isDraft value false. I need only objects having isDraft value true. I have tried all possible ways but am not able to find a solution for this. Can anyone help me with this?
Below are the schema, query and response.
Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Contract = new Schema({
name: {
type: String,
unqiue: true,
required: true
},
version: [
{
no: {
type: Number,
required: true
},
sections: [
{
sectionName: {
type: String,
required: true
},
clause: [{
description: {
type: String,
required: true
},
}]
}
],
approvedBy: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
}
],
acceptedBy: [
{
name: {
type: String,
},
eamil: {
type: String,
},
}
],
isDraft: {
type: Boolean,
required: true
},
date: {
type: Date,
default: Date.now
}
}
],
createdBy: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
});
module.exports = mongoose.model('contract', Contract);
Query
query = {
$and: [
{ createdBy: clientAdminDetails._id },
{ "version.isDraft": true }
],
};
await Contract
.find(query)
.skip(req.body.noOfItems * (req.body.pageNumber - 1))
.limit(req.body.noOfItems)
.exec((err, contract) => {
if (err) {
return res.json(err);
}
Contract.countDocuments(query).exec((count_error, count) => {
if (err) {
return res.json(count_error);
}
return res.json({
total: count,
page: req.body.pageNumber,
pageSize: contract.length,
contracts: contract
});
});
});
Response
{
"total": 1,
"page": 1,
"pageSize": 1,
"contracts": [
{
"_id": "61449469775..",
"name": "Octavia Blankenship",
"version": [
{
"_id": "614496593cc..",
"sections": [
{
"_id": "61449469775..",
"sectionName": "Est dolore dolorem n Updated `1323",
"clause": [
{
"_id": "614494697..",
"description": "Numquam nostrud et a"
}
]
}
],
"isDraft": false,
"no": 1,
"approvedBy": [],
"acceptedBy": [],
"date": "2021-09-17T13:21:29.509Z"
},
{
"_id": "614496122904ee4e046fbee8",
"sections": [
{
"_id": "6144955a8c0061025499606f",
"sectionName": "Praesentium suscipit",
"clause": [
{
"_id": "6144955a8c00610254996070",
"description": "Velit aperiam ut vel"
}
]
}
],
"isDraft": true,
"no": 2,
"approvedBy": [],
"acceptedBy": [],
"date": "2021-09-17T13:20:18.128Z"
}
],
"createdBy": "614367e980b29e6c...",
"__v": 0
}
]
}
This is why using your query you are telling mongo "Give me a document where createdBy is desired id and version.isdraft is true" So, as the DOCUMENT contains both values, is returned, even existing false into the array.
To solve this you have many ways.
First one is using $elemMatch into projection (docs here). But using this way only the first element is returned, so I think you prefer other ways.
So you can use an aggregation query using $filter like this:
First $match by values you want (as in your query).
Then override version array filtering by values where isDraft = true.
db.collection.aggregate([
{
"$match": {
"createdBy": "",
"version.isDraft": true
}
},
{
"$set": {
"version": {
"$filter": {
"input": "$version",
"as": "v",
"cond": {
"$eq": [
"$$v.isDraft",
true
]
}
}
}
}
}
])
Example here
This question already has answers here:
Mongoose/Mongodb: Exclude fields from populated query data
(4 answers)
Closed 2 years ago.
I just not want to pass user id in discussion array.
Now I getting back from this route like this.
{
"_id": "5f4600ab7ec81f6c20f8608d",
"name": "2",
"category": "2",
"description": "2",
"deadline": "2020-08-10",
"discussion": [
{
"date": "2020-09-03T06:12:15.881Z",
"_id": "5f5089bd265ec85b896f8491",
"user": {
"_id": "5f5089a2265ec85b896f848f",
"userName": "MdJahidHasan01"
},
"text": "3"
},
{
"date": "2020-09-03T06:12:15.881Z",
"_id": "5f5089ae265ec85b896f8490",
"user": {
"_id": "5f5089a2265ec85b896f848f",
"userName": "MdJahidHasan01"
},
"text": "2"
}
]
}
But I want to get like this
{
"_id": "5f4600ab7ec81f6c20f8608d",
"name": "2",
"category": "2",
"description": "2",
"deadline": "2020-08-10",
"discussion": [
{
"date": "2020-09-03T06:12:15.881Z",
"_id": "5f5089bd265ec85b896f8491",
"user": {
"userName": "MdJahidHasan01"
},
"text": "3"
},
{
"date": "2020-09-03T06:12:15.881Z",
"_id": "5f5089ae265ec85b896f8490",
"user": {
"userName": "MdJahidHasan01"
},
"text": "2"
}
]
}
Select does not working here. I just not want to pass user id in discussion array just username.
As I use user id for authorization. So it is not an good idea to send user id.
Project Model
const mongoose = require('mongoose');
const projectSchema = new mongoose.Schema({
name: {
type: String,
require: true
},
category: {
type: String,
require: true
},
description: {
type: String,
require: true
},
deadline: {
type: String,
require: true
},
discussion: [
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
date: {
type: Date,
default: Date.now()
},
text: {
type: String,
require: true
}
}
]
});
module.exports = mongoose.model('Project', projectSchema);
Project Details Route
router.get('/:projectId',async (req, res) => {
try {
const project = await Project.findById(req.params.projectId)
.populate('discussion.user', 'userName')
.select('-discussion.user._id')
console.log(project);
await res.status(200).json(project);
} catch (error) {
console.log(error);
return res.status(400).json({ 'error': 'Server Error' });
}
})
Just add this after the .populate:
delete project.discussion._id
i'm new to MongoDB and trying to build a simple chat app using Node.Js and MongoDB using mongoose Js. and i'm stuck here for last 2 days so need help!!
Tested most of the related answer of stack overflow but not getting desirable result.
What i want to achieve is something similar we see in chat application like Facebook Messenger and whatsApp web where in one side we see all our conversation list which show last message and person profile.
an example here http://roba.laborasyon.com/demos/dark/ (left sidebar)
this is how my model look like
const chat = new Schema({
to:{
type:Schema.Types.ObjectId,
ref:"User",
required:true,
},
from:{
type:Schema.Types.ObjectId,
ref:"User",
required:true,
},
seenbySender:Boolean,
seenByReceiver:Boolean,
isFile:{
type:Boolean,
default:false
},
file:{
type:Object,
required:false,
},
text:String,
},{timestamps:true});
In My Controller or route file (this is not my code but i tried similar logic they all return empty array or error)
exports.test = (request,response,next) => {
let {user} = request.body;
const u=await User.findById(user);
//Chat.find({from:user}).populate('from').populate('to').then(r => response.json(r));
//user ="5f46319ac483a43d98ae3626";
Chat.aggregate([
{$match:{$or:[{"to":user},{"from":user}]}},
{
$group:{"_id":
{
"text":{
$cond:[
{
$gt:[
{$substr:["$to",0,1]},
{$substr:["$from",0,1]}]
},
{$concat:["$to"," and ","$from"]},
{$concat:["$from"," and ","$to"]}
]
}
},
"text":{$first:"$text"}
}
}]).then(result => {
response.json(result)
}).catch(error => {
console.log("[[error]]",error)
response.json({error})
});
}
Here is data i'm working with (exported JSON file)
[
{
"_id": {
"$oid": "5f4a3ae0a7ff491f3024668e"
},
"isFile": false,
"to": {
"$oid": "5f46325ec483a43d98ae3627"
},
"from": {
"$oid": "5f46319ac483a43d98ae3626"
},
"text": "Hi John,Yash here!",
"createdAt": {
"$date": "2020-08-29T11:24:16.416Z"
},
"updatedAt": {
"$date": "2020-08-29T11:24:16.416Z"
},
"__v": 0
},
{
"_id": {
"$oid": "5f4a3affa7ff491f3024668f"
},
"isFile": false,
"to": {
"$oid": "5f46319ac483a43d98ae3626"
},
"from": {
"$oid": "5f46325ec483a43d98ae3627"
},
"text": "hello Yash - John",
"createdAt": {
"$date": "2020-08-29T11:24:47.519Z"
},
"updatedAt": {
"$date": "2020-08-29T11:24:47.519Z"
},
"__v": 0
},
{
"_id": {
"$oid": "5f4a3b25a7ff491f30246690"
},
"isFile": false,
"to": {
"$oid": "5f4632c8c483a43d98ae3628"
},
"from": {
"$oid": "5f46319ac483a43d98ae3626"
},
"text": "Hello Don, Yash this side.",
"createdAt": {
"$date": "2020-08-29T11:25:25.067Z"
},
"updatedAt": {
"$date": "2020-08-29T11:25:25.067Z"
},
"__v": 0
}
]
So what i need is last message of user he chatted with, with the user reference. in this case for Id: 5f46319ac483a43d98ae3626 the last 2 objects should be render
Thanks a lot!!
You can try using $split to get limited records,
db.collection.aggregate([
{
$match: {
$or: [
{ "to": ObjectId("5f46319ac483a43d98ae3626") },
{ "from": ObjectId("5f46319ac483a43d98ae3626") }
]
}
},
// for descending order
{ $sort: { updatedAt: -1 } },
{
$group: {
_id: {
$cond: [
{ $eq: ["$to", ObjectId("5f46319ac483a43d98ae3626")] },
{ $concat: [{ $toString: "$to" }, " and ", { $toString: "$from" }] },
{ $concat: [{ $toString: "$from" }, " and ", { $toString: "$to" }] }
]
},
updatedAt: { $first: "$updatedAt" },
// push messages
messages: { $push: "$$ROOT" }
}
},
// order by descending order
{ $sort: { updatedAt: -1 } },
// limit to 2 messages only
{ $addFields: { messages: { $slice: ["$messages", 2] } } }
])
Playground
for joining user data you can use $lookup
I guess you can use this schema for a chat
MessageSchema = new mongoose.Schema({
from: {
type: string,
required: true,
},
to: {
type: string,
required: true,
},
time: {
type: Date,
default: Date.now(),
},
message: {
type: string,
required: true,
},
});
ChatSchema = new mongoose.Schema({
firstUserId:{
type: mongoose.Schema.Types.ObjectId,
required: true,
},
secondUserId:{
type: mongoose.Schema.Types.ObjectId,
required: true,
},
Chat: MessageSchema,
})
and data will be as this way
[
{
firstUserId: "hjakdsf323275lks",
secondUserId: "asdfe2342232aas",
Chat: [
{
from: "hjakdsf323275lks",
to: "asdfe2342232aas",
time: "18/7/2020 20:06:09",
message: "Hi ",
},
{
from: "asdfe2342232aas",
to: "hjakdsf323275lks",
time: "18/7/2020 21:07:09",
message: "hello ",
},....
],
},
];
I have two schemas: 'Leads' and 'LeadsCategory'.
Leads Schema:
const id = mongoose.Schema.Types.ObjectId;
const leadsSchema = mongoose.Schema(
{
_id: id,
userId: { type: id, ref: "User", required: true },
leadName: String,
leads: [
{
_id: id,
name: String,
mobile: Number,
address: String,
education: {
school: String,
graduation: String
},
leadType: { type: id, ref: "LeadsCategory", required: true }
}
]
},
{
timestamps: true
}
);
module.exports = mongoose.model("lead", leadsSchema);
Leads Category Schema:
const id = mongoose.Schema.Types.ObjectId;
const leadsCategorySchema = mongoose.Schema({
_id: id,
name: {
type: String,
required: true
},
leadsData: [{ type: id, ref: 'lead' }]
},
{ timestamps: true }
);
module.exports = mongoose.model("LeadsCategory", leadsCategorySchema);
I'm referencing the leadsCategory as soon as new lead is created and it does populate my leadsCategory into the Leads controller.
So my final data inside 'Leads collection' looks like this:
[
{
"_id": "5e8832dde5d8273824d86502",
"leadName": "Freshers",
"leads": [
{
"education": {
"school": "LPS",
"graduation": "some school"
},
"location": {
"state": "delhi",
"country": "india"
},
"name": "Joey",
"mobile": 1524524678,
"_id": "5e8832dde5d8273824d86500",
"leadType": {
"_id": "5e88285f5dda5321bcc045a6",
"name": "all"
}
},
{
"education": {
"school": "DAV",
"graduation": "some school"
},
"location": {
"state": "delhi",
"country": "india"
},
"name": "Ben",
"mobile": 1524524678,
"_id": "5e8832dde5d8273824d86501",
"leadType": {
"_id": "5e88285f5dda5321bcc045a6",
"name": "all"
}
}
]
}
]
But now I need to associate the leads data into my 'leadsCategory' collection so that I can query the leads data according to the leadType created. For now, I have only one 'leadType':'all'. But further, I will create more types and populate the data accordingly.
I tried something like this:
exports.get_leads_type_all = (req, res) => {
LeadsCategory.find()
.populate('leadsData')
.then( data => {
res.json(data)
})
}
But this returns me only empty array like this:
{ "leadsData": [],
"_id": "5e88285f5dda5321bcc045a6",
"name": "all",
"createdAt": "2020-04-04T06:25:35.171Z",
"updatedAt": "2020-04-04T06:25:35.171Z",
"__v": 0
},
Please help me to associate and related this data. I have tried lot's of thins but could not make it work.
try this:
exports.get_leads_type_all = (req, res) => {
LeadsCategory.find()
.populate('leadsData')
.execPopulate()
.then( data => {
res.json(data)
})
}
https://mongoosejs.com/docs/api/document.html#document_Document-execPopulate
I'm pretty new to Mongoose and MongoDB in general so I'm having a difficult time figuring out if something like this is possible:
I'm trying to filter only those document who has created_by_id not [].
This is schema.
var CampaignSchema = new Schema({
name: { type: String, required: true },
description: { type: String, required: true },
budget: { type: String, required: true },
tags: { type: [ String ], required: true },
status: { type: Number },
payment_id: { type: String },
created_by_id: [{ type: Schema.Types.ObjectId, ref: 'User' }],
attached_file: {
uploaded_on: { type: Date, default: Date.now },
uploaded_by: { type: String, required: true },
},
added_url: {
added_on: { type: Date, default: Date.now },
added_by: { type: String, required: true },
},
updated_by: { type: String },
created_on: { type: Date, default: Date.now },
updated_on: { type: Date }
});
This is code:
_getCampaigns(req, res){
var token = helpersMethods.getToken(req.headers);
var page = parseInt(req.query.page) || 0; //for next page pass 1 here
var limit = parseInt(req.query.limit) || 10;
var term = new RegExp(req.query.search, 'i');
var obj = { "created_by_id": { "$ne": [] } };
if (token) {
Campaign.find(obj)
.populate({
path : 'created_by_id',
match : {
$or: [
{ name: { $regex: term }},
]
}
})
.sort({ updateAt: -1 })
.skip(page * limit)
.limit(limit)
.exec((err, doc) => {
if (err) {
return res.json(err);
}
Campaign.count(obj).exec((count_error, count) => {
if (err) {
return res.json(count_error);
}
return res.json({
total: count,
page: page,
pageSize: doc.length,
campaigns: doc
});
});
});
} else {
return res.status(403).send({success: false, msg: 'Unauthorized.'});
}
}
And i'm getting postman output like this, but i do not want the object who don't have created_by_id array:
{
"total": 2,
"page": 0,
"pageSize": 2,
"campaigns": [
{
"attached_file": {
"uploaded_by": "Demo user",
"uploaded_on": "2019-01-29T11:07:27.475Z"
},
"added_url": {
"added_by": "Demo user",
"added_on": "2019-01-29T11:07:27.475Z"
},
"tags": [
"tag1",
"tags2"
],
"_id": "5c5033ef28f63c72808f2225",
"created_by_id": {
"_id": "5c4965d477e7191c4d40b412",
"name": "Demo user",
"email": "demo#arth.tech",
"phone": "9918XXXXXX",
"type": "1",
"admin_rights": "1",
"password": "$2a$10$6T2ulNN60fBG9/vFgf8XhetkcWb/2zDxGXUMXMRi2Bltn8s1NEkbq",
"__v": 0,
"createdAt": "2019-01-24T07:31:03.327Z",
"loggedIn_at": "2019-01-30T06:33:04.388Z",
"loggedOut_at": "2019-01-24T08:03:44.091Z"
},
"name": "Test Campaign",
"description": "Discription of test campaign",
"budget": "2000",
"updated_by": "Demo User",
"created_on": "2019-01-29T11:07:27.475Z",
"__v": 0
},
{
"attached_file": {
"uploaded_by": "Demo User",
"uploaded_on": "2019-01-29T13:08:48.021Z"
},
"added_url": {
"added_by": "Demo user",
"added_on": "2019-01-29T13:08:48.021Z"
},
"tags": [
"test1",
"test2"
],
"_id": "5c505060b97f871123d97990",
"created_by_id": [],
"name": "Hello Campaign",
"description": "Description of Hello campaign",
"budget": "1000",
"updated_by": "Hello user",
"created_on": "2019-01-29T13:08:48.021Z",
"__v": 0
}
]
}
I want only those objects who has created_by_id, the actual output i want.
{
"total": 1,
"page": 0,
"pageSize": 1,
"campaigns": [
{
"attached_file": {
"uploaded_by": "Demo user",
"uploaded_on": "2019-01-29T11:07:27.475Z"
},
"added_url": {
"added_by": "Demo user",
"added_on": "2019-01-29T11:07:27.475Z"
},
"tags": [
"tag1",
"tags2"
],
"_id": "5c5033ef28f63c72808f2225",
"created_by_id": {
"_id": "5c4965d477e7191c4d40b412",
"name": "Demo user",
"email": "demo#arth.tech",
"phone": "9918XXXXXX",
"type": "1",
"admin_rights": "1",
"password": "$2a$10$6T2ulNN60fBG9/vFgf8XhetkcWb/2zDxGXUMXMRi2Bltn8s1NEkbq",
"__v": 0,
"createdAt": "2019-01-24T07:31:03.327Z",
"loggedIn_at": "2019-01-30T06:33:04.388Z",
"loggedOut_at": "2019-01-24T08:03:44.091Z"
},
"name": "Test Campaign",
"description": "Discription of test campaign",
"budget": "2000",
"updated_by": "Demo User",
"created_on": "2019-01-29T11:07:27.475Z",
"__v": 0
}
]
}
can any one help?
I did , what i want. here is updated code.
_getCampaigns(req, res){
var token = helpersMethods.getToken(req.headers);
var page = parseInt(req.query.page) || 0; //for next page pass 1 here
var limit = parseInt(req.query.limit) || 10;
var term = new RegExp(req.query.search, 'i');
var obj = {};
if (token) {
Campaign.find(obj)
.populate({
path : 'created_by_id',
match : {
$or: [
{ name: { $regex: term }},
]
}
})
.sort({ updateAt: -1 })
.skip(page * limit)
.limit(limit)
.exec((err, docs) => {
if (err) {
return res.json(err);
}else{
docs = docs.filter(function(doc) {
return doc.created_by_id.length != 0;
});
Campaign.count(obj).exec((count_error, count) => {
if (err) {
return res.json(count_error);
}else{
return res.json({
total: count,
page: page,
pageSize: docs.length,
campaigns: docs
});
}
});
}
});
} else {
return res.status(403).send({success: false, msg: 'Unauthorized.'});
}
}