how to use mongoose populate/ref like this? - mongodb

I'm tring to find every sensor(according to sensor_id) infomation.
the sensor_id is related _id.
my code is:
//this is vnodeInfo
var vnodesSchema = new Schema({
"_id": {
type: Schema.Types.ObjectId //this is ref sensor_id
},
"node_id": {
type: String
},
"name": String,
"sensors": [
{
"sensor_id": {
type: Schema.Types.ObjectId,
ref: "sensors"
},
"name": String,
"alias": String
}
]
});
//this is sensorsInfo
var sensorsSchema = new Schema({
"_id": {
type: Schema.Types.ObjectId //this is link
},
"node_id": {
type: String,
ref: "Nodes"
},
"order": String,
"name": String,
"alias": String,
"low_limit": {
type: Number
},
"high_limit": {
type: Number
},
"value": {
type: Number
},
"state": String,
"last_update": {
type: Date, default: Date.now
}
});
this is my statics method:
I'm tring use sensor.sensor_id related to sensorSchema
"sensor_id==_id" use this ref to get sensors's infomation
findSensorsById: function (vnodeId,callback) {
//use sensors.sensor_id to get sensorinfo
//this is a static method.
return this.findById(vnodeId).populate('sensors.sensor_id').exec(callback)
}

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' }
});

mongodb/mongoose + graphql When referencing a model with the id, the data is null

My apologies if this doesn't make too much sense, I am starting to get more comfortable with Mongodb using mongoosejs and also using graphql. I am trying to create a db that will contain transactions made by users, said transactions should be part of a specific category.
These are my typedefs:
type Auth {
token: ID!
user: User
}
type User {
_id: ID
email: String
expenses: [Expense]
}
type Category {
_id: ID
name: String
}
type Expense {
_id: ID
expenseName: String
expenseAmount: Float
expenseDate: String
category: Category
}
type Query {
me: User
users: [User]
user(email: String!): User
expenses(email: String!): [Expense]
expense(id: ID!): Expense
categories: [Category]
}
type Mutation {
login(email: String!, password: String!): Auth
addCategory(name: String!): Category
addUser(email: String!, password: String!, firstName: String!, lastName: String!): Auth
addExpense(expenseName: String!, expenseAmount: Float!, categoryId: ID!): Expense
}
And my resolver for the expense/transaction:
addExpense: async (parent, args, context) => {
if(context.user) {
const expense = await Expense.create({
expenseName: args.expenseName,
expenseAmount: args.expenseAmount,
category: args.categoryId,
});
await User.findByIdAndUpdate(
{ _id: context.user._id },
{ $push: { expenses: expense._id } },
{ new: true }
);
return expense;
}
throw new AuthenticationError("You must be logged in!");
}
Just in case you need it, these are my schemas:
For the user schema:
const userSchema = new Schema({
email: {
type: String,
required: true,
unique: true,
match: [/.+#.+\..+/, "Must match an email address!"],
},
password: {
type: String,
required: true,
minlength: [8, "Password must be at least 8 characters long!"],
},
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
expenses: [
{
type: Schema.Types.ObjectId,
ref: "Expense",
}
]
});
For the expense/transaction:
const expenseSchema = new Schema({
expenseName: {
type: String,
required: true,
minlenght: 1,
},
expenseAmount: {
type: Number,
required: true,
min: 0.01,
},
expenseDate: {
type: Date,
default: Date.now,
},
category: {
type: Schema.Types.ObjectId,
ref: "Category",
required: true,
}
});
For the category creation:
const categorySchema = new Schema({
name: {
type: String,
required: true,
},
});
So when I run it in apollo server after adding an expense/transaction, it shows everything but it will not show the name for the category, it will always show null:
"data": {
"me": {
"_id": "630a42ea7f7be79ba1d4114c",
"email": "admin#test.com",
"expenses": [
{
"_id": "630af7b795e5fd336ba708be",
"expenseName": "Mom",
"expenseAmount": 70,
"expenseDate": "1661663159375",
"category": {
"_id": "630af5fd2d4b15974802c026",
"name": null
}
},
{
"_id": "630af85695e5fd336ba708c2",
"expenseName": "Mom",
"expenseAmount": 70,
"expenseDate": "1661663318985",
"category": {
"_id": "630a432b7f7be79ba1d4114e",
"name": null
}
}
]
}
}
}
Could someone help me figure out what am I missing? Apologies if I am sharing too much

Duplicate error even though collection is empty

I try to insert multiple documents into my MongoDB collection, but whatever I do, I get a duplicate error. I made sure that there should be no duplicates possible by dropping the whole collection.
I tried it with .insertMany(), .save(), .create() - none of them do work. Though the docs get inserted, I still get the duplicate error 11000.
My function to insert the docs:
Words.prototype.addManyGeneralWordsEN = async function(words) {
await generalWordEN.create(words).then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err.code)
})
}
// add words to database
await this.addManyGeneralWordsEN(wordsToAdd)
My schema:
const generalWordENSchema = new mongoose.Schema(
{
german: {
type: String,
required: true
},
english: {
type: String,
required: true
},
partOfSpeech: {
required: true,
type: String
},
example: {
default: null,
type: String,
},
defintion: {
default: null,
type: String,
},
image: {
default: null,
type: String,
},
audio: {
default: null,
type: String,
},
level: {
default: null,
type: Number,
},
}
)
generalWordENSchema.index({ german: 1, english: 1, partOfSpeech: 1}, { unique: true })
module.exports = generalWordENSchema
My sample data:
[
{
"english": "clothes",
"german": "Kleidung",
"partOfSpeech": "noun",
"example": "My wife's wardrobe is filled with beautiful clothes.",
"definition": "",
"image": "",
"audio": "",
"level": ""
},
{
"english": "men's clothing",
"german": "Herrenbekleidung",
"partOfSpeech": "noun",
"example": "Men's clothing is on the second floor.",
"definition": "",
"image": "",
"audio": "",
"level": ""
}
]
The problem is probably on this line
generalWordENSchema.index({ german: 1, english: 1, partOfSpeech: 1}, { unique: true })
You created an index for the collection and used partOfSpeech as unique, but you have two documents with the same value noun.
It should work if you change it to:
generalWordENSchema.index({ german: 1, english: 1 }, { unique: true });
You also have a typo on the Schema declaration that might cause you different issues. You typed defintion instead of definition.

How to populate multilevel array in mongoose

I have a Quiz Model with array of Section and each Sections has array of reference to Question.
I want to populate Quiz with question.
QuizModel
var quizSchema = new Schema({
name: String,
code: Number,
creator: String,
createdBy: { type: Schema.Types.ObjectId, ref: 'user' },
section:[{
title: String,
questions: [{type: Schema.Types.ObjectId ,ref: 'question'}]
}],
createdOn: {type:Date, default:Date.now}
});
and questionModel
var questionSchema = new mongoose.Schema(
{
question: String,
answer: [String],
correct: Number,
createdOn: {type:Date, default:Date.now}
});
I have following the official mongoose documentation for populating
http://mongoosejs.com/docs/populate.html#deep-populate
My attempt
quizSchema.find({_id: quiz_id})
.populate({
path: 'section' ,
populate: {
path: 'section.questions',
model: 'questionSchema'
}
})
.exec( function (err, result) {
if (err) return done(err,null);
console.log("list of questions are" + result);
return done(err, result);
});
}
The output I am getting is list of question's id not the actual question.
{
"status": "success",
"message": "Quiz data",
"result": [
{
"_id": "57fd5912ec0ad6bc8b67d71c",
"name": "My Quiz",
"creator": "foo",
"__v": 0,
"code": 124,
"createdOn": "2016-10-11T21:26:42.774Z",
"section": [
{
"_id": "57fd7e82c20a2fe5da3ed569",
"questions": [
"57fd7f8560e98fe710878820",
"57fd7f9d60e98fe710878821",
"57fd81408b20dae9108d347c",
"57fd81408b20dae9108d347d",
"57fd826aea5159ea5ff2f1a9",
"57fd82ab0dbc0feaa753e50c",
"57fd82efd789afeb0353f036",
"57fd84b0fef6a2ed21fad5ae",
"57fd84cc5dab10ed471bcaf5",
"57fd84cd5dab10ed471bcaf6"
]
},
{
"title": "next section",
"_id": "57fff1e0f1913138c27e50a0",
"questions": [
"57fff242f1913138c27e50a1"
]
}
]
}
]
}
I think I am doing something wrong with populate field, but not sure .
Just alter your query to
quizSchema.find({_id: quiz_id})
.populate({
path: 'section.questions'
})

Meteor simple schema issue

I'm getting null array value in main_categories. My schema is for brand collection:
Schema Definition
Schema.main_category = new SimpleSchema({
name: {type: String},
icon_image: {type: String},
description: {type: String}
});
Main_Category.attachSchema(Schema.main_category);
Schema.brand = new SimpleSchema({
name: {
type: String,
},
admin_number: {
type: String,
},
company_name: {
type: String,
},
owner_name: {
type: String,
},
owner_number: {
type: String,
},
admin_comment: {
type: String,
},
address: {
type: Schema.address,
},
logo_image: {
type: String
},
staffs: {
type: Array
},
"staffs.$": {
type: Object
},
"staffs.$.type": {
type: String,
allowedValues: ['admin']
},
"staffs.$.user_id": {
type: String
},
main_categories: {
type: [Schema.main_category]
},
sub_categories: {
type: [Schema.sub_category]
},
showcase: {
type: Boolean
}
});
Brand.attachSchema(Schema.brand);
Implementation
"addBrandMethod": function(jsonData) {
var json = {
name: jsonData.brandName,
admin_number: jsonData.adminNumber,
company_name: jsonData.companyName,
address: jsonData.companyAddress,
owner_name: jsonData.ownerName,
owner_number: jsonData.ownerNumber,
admin_comment: "jsonData.adminComment",
logo_image: "fasdfa",
staffs: [{
type: "admin",
user_id: "jaskjjkj"
}],
main_categories: [{
"_id": "uBibwEqaoDkZtXhsR",
"name": "Hair",
"icon_image": "nbdenck",
"description": "Hair Cut with Massage"
}
],
sub_categories: Sub_Category.find().fetch(),
showcase: true
};
Brand.insert(json);
return "Success";
}
Try removing the _id key from the main_categories array.
You didn't specify the _id key in the schema and simple-schema will only add the key when it's a schema that's attached to a collection.
I was getting main_categories object null because main_categories file alphabetically down from brand schema file.. and in brand schema file i was getting object of main_categories schema undefined. when i paste file up to brand schema file then problem solve..