Mongoose find() returning irrelevant documents - node.js

I have a schema like this one:
var WorkSchema = new mongoose.Schema({
works: [{
name:String,
times:[{
day:String,
timeOfDay:[{
startTime: Number,
endTime: Number
}],
date: Date
}],
locations:[String]
}],
worker: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
},{timestamps: true}
);
I have saved a lot of document on this schema. Now, i want to find the documents which has name:'idle'. I'm using Worker.find({'works.name':req.body.name}) but it's not giving me the exact documents i want and giving irrelevant documents. But in MongoDb Compass, this exact line is finding the desired documents.
How do i find the values in mongoose?

Related

How to populate sub document of another model in mongoose?

I have two mongodb model as following.
const CompanySchema = new Schema(
{
sections: [{
name: { type: String },
budgets: [{ // indicates from CalcSchema
index: { type: Number },
title: { type: String },
values: [Number],
sum: { type: Number, default: 0 },
}],
}]
},
{ timestamps: true }
);
const CalcSchema = new Schema({
budget: {
type: Schema.Types.ObjectId, // I want to populate this field. this indicates budget document in Company model
ref: "Company.sections.budgets" //it's possible in mongoose?
},
expense: {
type: Number,
default: 0
}
});
budget field indicate one of budgets field in CompanySchema.
So I want to populate when get Calc data.
But I don't how to populate embedded document.
I tried set ref value to ref: "Company.sections.budgets". but it's not working.
Please anyone help.
Finally, I found answer myself.
There is useful plugin for it.
https://github.com/QuantumGlitch/mongoose-sub-references-populate#readme
And I learned that my schema structure was wrong. It's anti-pattern in mongodb.

is there a way to populate an array inside an object inside an array of objects in mongoose

So, I have 3 schemas,
User
const UserSchema = new mongoose.Schema({
...,
weekly: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Weekly'
}]
});
Weekly
const weeklyAnalyticSchema = new mongoose.Schema({
daily: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'DailyAnalytic'
}],
weekStart: {
type: Date,
// default: addDaystoDate(1)
},
weekEnd: {
type: Date,
// default: addDaystoDate(7)
}
})
Daily
const Daily = new mongoose.Schema({
date: Date,
foo: bar
})
I'm trying to populate the daily array inside the weekly array,
like so...
I do this, following the documentation from mongoosejs mongoose deep populate
let found = await db.User.findById(req.user._id).populate({
path: "weeklyAnalytics",
populate: {
path: "dailyAnalytics"
}).exec()
and it comes out like this
daily: [ 1],
weekly: [
{
daily: [Array],
_id: 1,
__v: 0
}
],
i've tried many others as well and read and modified other peoples code, but I can't seem to get that daily inside the weekly to populate.
why does the answer always come up to the questioner after he asks the question
i just have to do console.log(found.week) and everything will show up.
now I can do whatever.

Mongoose query to check for specific value in array of searched element

I have s schema like:
var EntitySchema = new Schema({
name : {type: String, default: null},
organizations : [{
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Organization'
}}]
});
I have an id of organization, How can I make a query for Entity.find({}) and find Entity that has this id in its organizations array?
I used this in mongo shell
db.entity.find({"organizations.id": { $in: [ObjectId("ididididididid")]}}).pretty()
and it worked, but it doesn't work in express method, do I do something wrong? Does $in works both ways? I have a feeling that its not what I should be using in this query.
As per mongo documentation, you can query as below
db.entity.find({ "organizations" : { $elemMatch: { "id" : ObjectId("ididididididid") } }}).pretty();
Ref:
https://docs.mongodb.com/manual/tutorial/query-array-of-documents/

Mongoose populate ObjectID from multiple possible collections

I have a mongoose model that looks something like this
var LogSchema = new Schema({
item: {
type: ObjectId,
ref: 'article',
index:true,
},
});
But 'item' could be referenced from multiple collections. Is it possible to do something like this?
var LogSchema = new Schema({
item: {
type: ObjectId,
ref: ['article','image'],
index:true,
},
});
The idea being that 'item' could be a document from the 'article' collection OR the 'image' collection.
Is this possible or do i need to manually populate?
Question is old, but maybe someone else still looks for similar issues :)
I found in Mongoose Github issues this:
mongoose 4.x supports using refPath instead of ref:
var schema = new Schema({
name:String,
others: [{ value: {type:mongoose.Types.ObjectId, refPath: 'others.kind' } }, kind: String }]
})
In #CadeEmbery case it would be:
var logSchema = new Schema({
item: {type: mongoose.Types.ObjectId, refPath: 'kind' } },
kind: String
})
But I did't try it yet...
First of all some basics
The ref option says mongoose which collection to get data for when you use populate().
The ref option is not mandatory, when you do not set it up, populate() require you to give dynamically a ref to him using the model option.
#example
populate({ path: 'conversation', model: Conversation }).
Here you say to mongoose that the collection behind the ObjectId is Conversation.
It is not possible to gives populate or Schema an array of refs.
Some others Stackoverflow people asked about it.
Soluce 1: Populate both (Manual)
Try to populate one, if you have no data, populate the second.
Soluce 2: Change your schema
Create two link, and set one of them.
var LogSchema = new Schema({
itemLink1: {
type: ObjectId,
ref: 'image',
index: true,
},
itemLink2: {
type: ObjectId,
ref: 'article',
index: true,
},
});
LogSchema.find({})
.populate('itemLink1')
.populate('itemLink2')
.exec()
Dynamic References via refPath
Mongoose can also populate from multiple collections based on the value of a property in the document. Let's say you're building a schema for storing comments. A user may comment on either a blog post or a product.
body: { type: String, required: true },
on: {
type: Schema.Types.ObjectId,
required: true,
// Instead of a hardcoded model name in `ref`, `refPath` means Mongoose
// will look at the `onModel` property to find the right model.
refPath: 'onModel'
},
onModel: {
type: String,
required: true,
enum: ['BlogPost', 'Product']
}
});
const Product = mongoose.model('Product', new Schema({ name: String }));
const BlogPost = mongoose.model('BlogPost', new Schema({ title: String }));
const Comment = mongoose.model('Comment', commentSchema);

MongoDB conditional query

We want to query a collection using two fields (ids) to find a specific conversation that has userOne and or userTwo with same id number like we want to find all the conversations that has 57e334af0e5fcc9e8e800177 id in userOne or userTwo
Mongoose Schema
userOne: {type: mongoose.Schema.Types.ObjectId, ref:'users'},
userTwo: {type: mongoose.Schema.Types.ObjectId, ref:'users'},
created_at: {type: Date, default: Date.now}
Query that we tried.
db.getCollection('conversations').find({
$or : [{userOne: "57e334af0e5fcc9e8e800177"}],
$or : [{userTwo: "57e334af0e5fcc9e8e800177"}]
})
Sample Conversation Object
_id: "57eae04c4efbb25487a00293"
created_at: "2016-09-27T21:10:36.236Z"
userOne: "57e334c00e5fcc9e8e800178"
userTwo: "57e334af0e5fcc9e8e800177"
You only need a single $or condition because it takes an array which you can put both your fields into. From the example on the MongoDB documentation:
db.inventory.find( { $or: [ { quantity: { $lt: 20 } }, { price: 10 } ] } )
So all you'd need to do is:
db.getCollection('conversations').find({
$or: [
{userOne: "57e334af0e5fcc9e8e800177"},
{userTwo: "57e334af0e5fcc9e8e800177"}
]
});

Resources