This is my schema:
Appliance = new Schema({
appliance_name: {type:String},
appliance_id: {type:String},
appliance_description: {type:String},
keywords: [{ type: String}],
appliance_type: { type: String},
appliance_status: { light: { write_state: Number, read_state: Number },
fan: {write_state: Number, read_state: Number, write_speed: Number, read_speed: Number}
}
});
Room= new Schema({
name: {type: String, required:true},
device_auth_code: {type: String},
alt_name: {type:String},
keywords: [{type: String}],
appliance: [Appliance]
});
Home = new Schema({
name: { type: String, required: true},
description: {type: String},
administrator: {type : mongoose.Schema.Types.ObjectId, ref: 'User', required: true},
users: [{
_id: {type : mongoose.Schema.Types.ObjectId, ref: 'User'},
email: {type: String},
name: { type: String},
status: { type: Number}
}],
rooms: [Room]
});
And here is the typical home.
"type": true,
"code": "GET_SUCCESS",
"homes": {
"_id": "58760ff6045e332b81449b42",
"description": "",
"administrator": "586df1e06485de5fc48b72a5",
"name": "CM",
"__v": 9,
"rooms": [
{
"name": "RK",
"alt_name": "RKa",
"_id": "58775437234451346ce3d967",
"appliance": [
{
"_id": "5877546f234451346ce3d968",
"appliance_type": "Light",
"appliance_name": "TubeLights",
"keywords": []
}
],
"keywords": []
}
],
"users": []
}
}
Home has nested array of rooms and each room has nested array of appliances.
Home.findOne({'room.appliance._id': appliance_id}) would return the whole document. The $ operator wouldn't work I would have to imagine.
Is it possible to receive that particular appliance or the whole document with that particular room and appliance only being returned?
How do I find a particular appliance and return that appliance?
Here you've used mongoose subdocs architecture in your home schema definition. So you could retrieve any particular room:
Home.findById(home_id, function(err, home){
var room = home.rooms.id(room_id);
res.json(room)
});
or a particular appliance:
Home.findById(home_id, function(err, home){
var room = home.rooms.id(room_id);
var appliance = room.appliance.id(appliance_id);
res.json(appliance)
});
Related
I'm fairly new to Mongo and Mongoose, so if this question is rather silly then feel free to point me in the right direction.
I have a API with models for users and stories that they published. When I display the users, I want the stories to show as well.
The relation is drawn rather simply:
const userSchema = mongoose.Schema({
username: {
type: String,
unique: true,
},
password: String,
firstName: {
type: String,
required: false,
},
lastName: {
type: String,
required: false,
},
birthday: {
type: Date,
},
bio: {
type: String,
required: false,
},
country: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Country',
},
stories: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Story',
}]
})
With a stories scheme declared as such:
const storySchema = new mongoose.Schema({
name: {
type: String,
max: 255,
},
url: {
type: String,
unique: true,
},
description: {
type: String,
required: false,
},
length: {
type: Number,
default: 0,
},
createdAt: Date,
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
language: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Country'
},
type: {
type: mongoose.Schema.Types.ObjectId,
ref: 'StoryType'
},
genre: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Genre'
},
})
I print the values using the simple find method (the action for now is only meant to show all of them.
app.get('/list-users', async (req, res) => {
const users = await User.find().populate('country').populate('stories').exec();
res.json(users);
});
Unfortunately, although the results show all the values properly, the stories array does not get populated at all.
[
{
"_id": "6127ce5b0576979256fd3e08",
"username": "test",
"password": "123",
"firstName": "tst",
"lastName": "tst",
"birthday": "1995-11-02T00:00:00.000Z",
"country": {
"_id": "6127c020f95eb5abf72f713a",
"name": "Poland",
"languange": "Polish",
"__v": 0
},
"stories": [],
"__v": 0
}
]
The docs have a clear indicator that such schemas will return an empty array, and I am aware I could just run a find by User and populate with that but I'm wondering what is the cleanest solution to apply in a situation like this.
Any help would be of great value.
I'm new to building rest api's with mongoose and express and have a question on how to use refPath correctly on my Models files and allowing for an array of items.
Below I have included the code for a model (built thus far) and would love any input on if I'm even close to building this correctly.
I will also include a screenshot that visually depicts the relationships I'm trying to create.
Those who answer questions here are GODS and I appreciate all the help this community has given me over the years!
const mongoose = require("mongoose");
const slugify = require("slugify");
const AlertSchema = new mongoose.Schema({
parentId: {
type: mongoose.Schema.ObjectId,
required: true,
refPath: "parentModel",
},
parentModel: {
type: String,
required: true,
enum: ["orgs", "clients"],
},
status: { type: String, default: "no-status" },
departments: [{ type: mongoose.Schema.Types.ObjectId, ref: "orgs" }],
createdAt: { type: Date, default: Date.now },
createdByType: [{ type: mongoose.Schema.Types.ObjectId, ref: "users" }],
createdById: [{ type: mongoose.Schema.Types.ObjectId, ref: "users" }],
groups: [{ type: String, default: "unGrouped" }],
stage: [{ type: mongoose.Schema.Types.ObjectId, ref: "stages" }],
children: { type: String },
resource: {
type: String,
match: [
/https?:\/\/(www\.)?[-a-zA-Z0-9#:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()#:%_\+.~#?&//=]*)/,
"Please use a valid URL with HTTP or HTTPS",
],
},
notes: [{ type: mongoose.Schema.Types.ObjectId, ref: "notes" }],
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: "comments" }],
priority: { type: String },
assignedTo: [{ type: mongoose.Schema.Types.ObjectId, ref: "users" }],
title: {
type: String,
required: [true, "Please add a title"],
maxlength: [50, "Title cannot be more than 50 characters"],
},
message: {
type: String,
required: [true, "Please add a message"],
maxlength: [500, "Message cannot be more than 500 characters"],
},
slug: String,
});
//create alert slug from the title
AlertSchema.pre("save", function (next) {
console.log("Slugify Ran", this.name);
this.slug = slugify(this.title, { lower: true });
next();
});
module.exports = mongoose.model("Testalert", AlertSchema);
Desired relationships diagram:
Is it possible to use mongoose's Populate Virtuals to populate the array of values it is referencing?
User Model
var userSchema = new mongoose.Schema({
auth_key: {type: String},
channels: [{
name: {type: String},
last_access: { type: Date, default: Date.now },
status: {type: String, default: false },
new_messages: {type: Number},
user_channel_group: {type: String}
}]
}, {
toJSON: {
virtuals: true
}
});
userSchema.virtual('channels.details', {
ref: 'channel',
localField: 'channels.name',
foreignField: 'name'
});
var user = mongoose.model('user', userSchema, 'user');
Channel Model
var channelSchema = new mongoose.Schema({
name: {type: String, required: true},
members: [{ type: String, required: true }],
displayName: {type: String},
type: {type: Number},
create_at: {type: Date, default: Date.now}
});
var channel = mongoose.model('channel', channelSchema, 'channel');
My query that I am using I want the virtual to present the channel details from each channel alongside the channels a user is subscribed to. so something like this..
[{
"_id": "588a82ff7fe89686fd2210b0",
"channels": [{
"details": {
"_id": "588a80fd7fe89686fd2210a8",
"name": "channel1",
"members": []
},
"name": "channel1"
}, {
"details": {
"_id": "588a80fd7fe89686fd2210a9",
"name": "channel2",
"members": []
},
"name": "channel2"
}],
"id": "588a82ff7fe89686fd2210b0"
}
...
]
My Query for this is ..
user.find({}).populate('channels.details').exec()
i want to sum each values of ObjectId field in relationship with moongose..
I have this:
`var wineSchema = new Schema({
name: { type: String },
code: { type:String},
type: {
type: String,
enum: ['Red','Rose','White']
},
winery: { type: String },
grape_type: { type: String },
year: { type: Number },
alcohol: { type: Number },
rates: [{ type: Schema.ObjectId, ref: "Rate" }],
Comments: [{ type: Schema.ObjectId, ref: "Comment" }],
});`
And this:
`var rate = new Schema({
user : { type: Schema.ObjectId, ref: "User" },
userName : {type: String},
wineName : { type: String},
rating : { type: Number}
});`
I want sum total values of each rate.rating inside wineSchema.rates..
How can I do it?
I'm trying to create a webapp with mongoose and nodejs. This is the first time i'm using mongoose and nodejs so i'm not quit good at it.
I have a person model:
var PERSON = new mongoose.Schema({
name: {type: String, required: true},
zipcode: {type: String, required: true},
city: {type: String, required: true},
street: {type: String, required: true},
address: {type: Number, required: true},
email: {type: String, required: true},
type: {type: String, enum: ['lid', 'passant'], required: true},
ships: {
type: [{
name: {type: String, required: true},
length: {type: Number, required: true},
type: {type: String, required: true},
picture: {type: Buffer, required: false}
}],
required: false
},
user: {
type: {
userName: {type: String, required: true},
password: {type: String, required: true},
passwordKey: {type: String, required: true},
roles: {type: [{type: mongoose.Schema.Types.ObjectId, ref: 'role'}], required: true}
},
required: false
}
},
{
collection: 'PERSON'
});
And the rol model:
var ROLE = new mongoose.Schema({
name: {type: String, required: true}
},
{
collection: 'ROLE'
});
When i'm trying to run a find query on the person model, I want to populate the user.roles array. But as a result it remains empty.
/ GET a specific person by id or type/
server.get('/api/person/:id', function (req, res, next) {
if (helper.isValidObjectID(req.params.id)) {
person.findById(req.params.id).populate("user.roles").exec(function (err, result) {
if (err) {
res.status(404).json(err);
} else {
res.status(200).json(result);
}
}
);
} else {
next();
}
}, function (req, res, next) {
person.find({type: req.params.id}).populate('user.roles').exec(function (err, result) {
if (err) {
res.status(404).json(err);
} else {
res.status(200).json(result);
}
});
});
and as a result i get:
{
"_id":"553f79d4f1481c0c14b42d59",
"name":"Wilco Boogert",
"zipcode":"4305RH",
"city":"Ouwerkerk",
"street":"baalpapenweg",
"address":2,
"email":"wilcoboogert17#gmail.com",
"type":"lid",
"user":{
"userName":"wboogert",
"password":"sha1$168fd599$1$502b965cb083ebdfcafb17e655455ef63779e1a1",
"passwordkey":"kfjvlksdfm",
"roles":[
]
},
"__v":0,
"ships":[
{
"name":"titanic",
"length":269,
"type":"Olympic-klasse",
"_id":"553f79d4f1481c0c14b42d5a"
}
]
}
The orginal object in the database is:
{
"_id": {
"$oid": "553f79d4f1481c0c14b42d59"
},
"name": "Wilco Boogert",
"zipcode": "4305RH",
"city": "Ouwerkerk",
"street": "baalpapenweg",
"address": 2,
"email": "wilcoboogert17#gmail.com",
"type": "lid",
"user": {
"roles": [
{
"$oid": "5522996f0fff331ed03cae6c"
}
],
"passwordkey": "kfjvlksdfm",
"password": "sha1$168fd599$1$502b965cb083ebdfcafb17e655455ef63779e1a1",
"userName": "wboogert"
},
"ships": [
{
"name": "titanic",
"length": 269,
"type": "Olympic-klasse",
"picture": "<Binary Data>",
"_id": {
"$oid": "553f79d4f1481c0c14b42d5a"
}
}
],
"__v": 0
}
so as you an see the roles is empty. And I search the web but i cannot find what the problem is. Can annyone help me?
You should replace this line :
roles: {type: [{type: mongoose.Schema.Types.ObjectId, ref: 'role'}], required: true}
with this one :
roles: {type: [{type: mongoose.Schema.Types.ObjectId, ref: 'ROLE'}], required: true}
In fact, the reference must be the exact same name as it's defined :
collection: 'ROLE'
It's case sensitive.