MongoDB Mongoose find using Map - mongodb

I have a mongoose schema like this:
const userSchema = new Schema( {
email:{ type: String, required: true, unique:true, index:true },
mobile:{ type: String },
phone:{ type: String },
firstname: { type: String },
lastname: { type: String },
profile_pic:{type:String},
socialHandles: {
type: Map,
of: String
},
active: {type:Boolean, default:true}
}, {
timestamps: true
} );
I want to query "give me user where socialHandles.instagram=jondoe" how do I do it?
Please help

Mongoose's map becomes a nested object in your database
{ "_id" : ObjectId(""), "socialHandles" : { "instagram": "jondoe" }, ..., "__v" : 0 }
so you can query it by using the dot notation:
let user = await User.findOne({ 'socialHandles.instagram': 'jondoe' });

Related

trying to populate a single field in each object inside an array of objects by dynamically picking the model to use with mongoose

I'm trying to use refPath to reference which collection to pull the population data from inside my schema, and even though it looks identical to the examples I've seen, its just not working.
Here is my schema for statesPersons, not super important, but it contains the activeWork array of objects.
import mongoose, {model, Schema} from "mongoose";
const statesPersonsSchema = new Schema(
{
profileId: {
type: String,
required: true,
unique: true,
},
department: {
type: String,
required: true,
index: true,
},
firstName: String,
lastName: String,
location: String,
org: String,
title: String,
jobDescription: String,
email: {
type: String,
lowercase: true,
},
phoneNumber: String,
activeWork: ["activeWork"],
emailList: [String],
jobAssignments: [String],
affiantInfo: {
affiantInfoTitle: String,
affiantInfoExperience: String,
},
assessments: [
{
assessdBy: {
type: Schema.Types.ObjectId,
ref: "statesPerson",
},
dueDate: Date,
questions: {},
},
],
},
{ strictPopulate: false }
);
export default mongoose.model("statesPersons", statesPersonsSchema);
Here is my schema for activeWork, the array of objects. This has the referenceId that I need to populate as well as the collectionType which I pull what collection it is from.
import mongoose, {model, Schema} from "mongoose";
const activeWorkSchema = new Schema(
{
active: Boolean,
collectionType: {
type: String,
enum: ["messages", "cases"],
},
referenceId: {
type: Schema.Types.ObjectId,
refPath: "collectionType",
},
sentBy: {
type: Schema.Types.String,
ref: "statesPersons",
},
sentTo: {
type: Schema.Types.String,
ref: "statesPersons",
},
timeRecived: Date,
dueDate: Date,
subject: String,
viewed: Boolean,
content: {},
},
{ strictPopulate: false }
);
export default mongoose.model("activeWork", activeWorkSchema);
And here is my query.
export async function getStatesPersonsActiveWorkByProfileId(req, res){
mongoose.set('debug', true);
try{
const { profileId } = req.params
const data = await statesPersons
.find({ profileId })
.populate('statesPersons.activeWork.referenceId')
.exec()
return res.send({
message: "success",
data: data,
status: 200 })
}catch(e) {
console.error(e.message)
return res.send({
message: "couldn't fetch active work",
data: null,
status: 500 })
}
}
its returning with the statesPersons object and the activeWork contains the objectId I need to populate, but its not populating. it looks like this.
"activeWork": [
{
"active": true,
"collectionType": "messages",
"referenceId": "63a49e3052658ce60c1dafcb",
"sentBy": "108416469928574003772",
"dueDate": "2018-02-21T11:16:50.362Z",
"subject": "testing",
"viewed": false,
"_id": "63a49e3052658ce60c1dafce"
I can force it to work by changing the query to be explicit.
const data = await statesPersons
.find({ profileId })
.populate({path: 'activeWork.referenceId', model: 'messages'})
.exec()
which looks like this.
activeWork": [
{
"active": true,
"collectionType": "messages",
"referenceId": {
"_id": "63a49e3052658ce60c1dafcb",
"involvedParties": [
"108416469928574003772",
"100335565301468600000"
],
"comments": [
{
"sender": [
"108416469928574003772"
],
"dateSent": "2022-12-22T18:13:04.604Z",
"content": "There is no way this is going to work.",
"_id": "63a49e3052658ce60c1dafcc"
}
],
But this wont work because I need it to be able to pull what model to use from the collectionType field
sorry for the late response , it seems like you are trying to populate the multilevel documents multilevel population.
here is an example.
db.statesPersonsSchema.find({ profileId }). populate({
path: 'activeWorkSchema',
populate: { path: 'referenceId' }
});

Mongo db error getting Error validating $lookup value. err=$lookup against an expression value is not allowed in this atlas tier

I am creating express server for the project and I used the mongodb for the database. I am getting error,
Error validating $lookup value. err=$lookup against an expression value is not allowed in this atlas tier.
movies schema,
const mongoose = require("mongoose");
const MovieSchema = new mongoose.Schema(
{
title: { type: String, required: true, unique: true },
desc: { type: String },
img: { type: String },
imgTitle: { type: String },
imgSm: { type: String },
trailer: { type: String },
video: { type: String },
year: { type: String },
limit: { type: Number },
genre: { type: String },
isSeries: { type: Boolean, default: false },
},
{ timestamps: true }
);
module.exports = mongoose.model("movies", MovieSchema);
My lists schema,
const ListSchema = new mongoose.Schema(
{
title: { type: String, required: true, unique: true },
type: { type: String },
genre: { type: String },
content: [
{ type: mongoose.Schema.Types.ObjectId, required: false, ref: "movies" },
],
},
{ timestamps: true }
);
lists schema has a content property and it's contains the ids of the movies.so I need to have get all movies in the list with sample size 4,so I write aggregation for the list schema for populating movies object in content property in list schema. So where is the bug in my code ?I hope your help!
so I coded it as,
const list = await List.aggregate([
{ $sample: { size: 4 } },
{
$lookup: {
from: "$movies",
foreignField: "_id",
localField: "content",
as: "content",
},
},
]);
}
res.status(200).json(list);

Return objects with ids matching the ids in another array mongoose

I'm having an issue running a query on my mongo DB. I want to return the objects that match the ids in the array of Ids. Not sure what I'm doing wrong everywhere online suggests doing it this exact way.
Mongoose Query
MovieSchema.statics.findKnownForMovies = function(ids) { return this.find({ id: { $in: [ids]}});
}
Mongoose Schema
const MovieSchema = new Schema({
adult: { type: Boolean },
category: {type: String},
id: { type: Number, required: true, unique: true },
poster_path: { type: String },
overview: { type: String },
release_date: { type: String },
original_title: { type: String },
genre_ids: [{ type: Number }],
original_language: { type: String },
title: { type: String },
backdrop_path: { type: String },
popularity: { type: Number },
vote_count: { type: Number },
video: { type: Boolean },
vote_average: { type: Number })
Array of ids
[ '577922', '487558', '429203' ]

How to update with mongoose

I have this record
{
"_id" : ObjectId("5dfdff479ad032cbbc673507"),
"selection" : [
{
"highlights" : "test",
"comment" : "CHANGE THIS",
"el" : "body:nth-child(2)>div:nth-child(2)#root>div.App>p:nth-child(1)"
},
{
"highlights" : "Barrett’s lyrical prose opens with a clever and tender solution",
"comment" : "",
"el" : "body:nth-child(2)>div:nth-child(2)#root>div.App>p:nth-child(2)"
}
],
"category" : [],
"status" : "",
"url" : "http://localhost:3000/theone",
"title" : "React App test",
"__v" : 4
}
And I want to update the comment. I have tried to use update and findOneAndUpdate and nothing is working. Here is my attempt
WebHighlight.findOneAndUpdate(
{
_id: req.params.highlight,
"selection.highlights": "test"
},
{ "selection.$.comment": "yourValue" }
);
That req.params.highlight is the id (I even hardcoded it)
I also tried this
WebHighlight.findById(req.params.highlight, (err, book) => {
var test = [...book.selection];
test[0].comment = "somethibf"
book.save();
res.json(book);
});
And nothing is working.
This is the model
const webhighlightsModel = new Schema({
selection: { type: Array, default: "" },
category: { type: Array, default: [] },
title: { type: String },
url: { type: String },
status: { type: String, default: "" }
});
Actually your code seems to work, but findOneAndUpdate returns the old document if you don't give {new: true} option.
I think for this reason, you think the update wasn't successfull, but if you check your collection, you will see the update.
WebHighlight.findOneAndUpdate(
{
_id: req.params.highlight,
"selection.highlights": "test"
},
{ "selection.$.comment": "yourValue" },
{ new: true }
)
.then(doc => res.send(doc))
.catch(err => res.status(500).send(err));
Also I think it would be better if selection had a sub schema like this:
const mongoose = require("mongoose");
const schema = new mongoose.Schema({
selection: [
new mongoose.Schema({
highlights: String,
comment: String,
el: String
})
],
category: { type: Array, default: [] },
title: { type: String },
url: { type: String },
status: { type: String, default: "" }
});
module.exports = mongoose.model("WebHighlight", schema);
So with this every selection would an _id field, and it would be better to update with this _id.
You should use the $set operator to update existing values:
WebHighlight.findOneAndUpdate(
{
_id: req.params.highlight,
"selection.highlights": "test"
},
{ '$set': { "selection.$.comment": "yourValue" } }
);

How to create Mongoose Schema for $near query

I have create a collection on MongoDB with with geo index "2dsphere" and I have an element with this structure in my colelction:
{
"_id" : ObjectId("573b2416130380fbf20c2610"),
"location" : {
"type" : "Point",
"coordinates" : [ -73.856077, 40.848447 ]
},
"marca" : "smart",
"stato" : "libera"
}
How can I create a schema in mongoose for this strucuture?
Assuming the collection is named Location, you could either define your schema as:
var locationSchema = new mongoose.Schema({
marca: { type: String, required: true },
stato: { type: String, required: true },
loc: {
type: {
type: "String",
required: true,
enum: ['Point', 'LineString', 'Polygon'],
default: 'Point'
},
coordinates: [Number]
}
});
locationSchema.index({'loc': '2dsphere'});
var Location = mongoose.model('Location', locationSchema);
or with the index:
var locationSchema = new mongoose.Schema({
marca: { type: String, required: true },
stato: { type: String, required: true },
loc: {
type: {
type: "String",
required: true,
enum: ['Point', 'LineString', 'Polygon'],
default: 'Point'
},
coordinates: [Number],
index: { type: '2dsphere', sparse: true }
}
});
var Location = mongoose.model('Location', locationSchema);