Mongoose select: false not working on location nested object - node.js

I want the location field of my schema to be hidden by default.
I added select: false property to it, but it is always returned when selecting documents...
var userSchema = new mongoose.Schema({
cellphone: {
type: String,
required: true,
unique: true,
},
location: {
'type': {
type: String,
required: true,
enum: ['Point', 'LineString', 'Polygon'],
default: 'Point'
},
coordinates: [Number],
select: false, <-- here
},
});
userSchema.index({location: '2dsphere'});
When calling :
User.find({ }, function(err, result){
console.log(result[0]);
});
the output is :
{
cellphone: '+33656565656',
location: { type: 'Point', coordinates: [Object] } <-- Shouldn't
}
EDIT : Explanation (thanks to #alexmac)
SchemaType select option must be applied to the field options not a type. In you example you've defined a complex type Location and added select option to a type.

You should firstly create locationSchema and after that use schema type with select: false:
var locationSchema = new mongoose.Schema({
'type': {
type: String,
required: true,
enum: ['Point', 'LineString', 'Polygon'],
default: 'Point'
},
coordinates: [Number]
}
});
var userSchema = new mongoose.Schema({
location: {
type: locationSchema,
select: false
}
});

Related

How to add GeoJson data with mongoose?

I am sending the object to create a user model.
"{
type: 'Point',
coordinates: [ 25.2239771, 51.4993224 ]
}"
And, here is the Mongoose Schema that I created.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserProfileSchema = new Schema(
{
userId: {
type: String,
// required: true,
unique: true,
},
userFirstName: {
type: String,
// required: true,
},
userLastName: {
type: String,
// required: true,
},
userGender: {
type: String,
// required: true,
},
userCoordinates: {
type: {
type: String,
default: 'Point',
},
coordinates: {
type: [Number],
index: '2dsphere',
},
},
},
{ collection: 'userprofilemodels' }
);
module.exports = UserProfile = mongoose.model(
'userprofilemodels',
UserProfileSchema
);
This is the code that I am using to add geoJson type file. However, I am getting an error.
I also tried to add index after the Schema has been defined
await new userProfileModel({
userId,
userFirstName,
userLastName,
userCoordinates,
})
.save()
.then(() => {
console.log('it worked!');
res.send('worked!');
})
.catch((error) => {
console.log('did not worl')
// console.log(error);
});
If I exclude userCoordinates, then it works. So, def my geoJson object is wrong. However, I have no clue where I have made mistakes.
Mongoose supports GeoJSON objects indexing so first add the "2dsphere" index to the userCoordintes rather than to the coordinates within the object in order to make it work.
userCoordinates: {
type: {
type: String,
default: 'Point',
},
coordinates: {
type: [Number],
default: undefined,
required: true
},
index: '2dsphere'
},
Make sure your userCoordinates looks something like this:
const userCoordinates = {
type: "Point",
coordinates: [coordinatesA, coordinatesB],
};
Taken from the mongoose documentation it seems the GeoJSON Type mustn't be only a String.
here is the example with location as a GeoJSON type:
const citySchema = new mongoose.Schema({
name: String,
location: {
type: {
type: String, // Don't do `{ location: { type: String } }`
enum: ['Point'], // 'location.type' must be 'Point'
required: true
},
coordinates: {
type: [Number],
required: true
}
}
});

Get data from mongodb with dynamic nested levels using nodejs and mongoose

For example
I have one table:
Menuid, menuname, parentid, levelid -- this is table
Consider the values:
Menuid:Pg, menuname:mainprogram, programid:'', levelid: 1
Menuid:sb, menuname:subprogram, programid:'Pg', levelid: 2
Menuid:cb, menuname:childprogram, programid:'sb', levelid: 3
Menuid:Pg2, menuname:mainprogram2, programid:'', levelid: 1
Output:
[ {
Menuid:'Pg',
Menuname:'mainprogram',
Children:[ {
Menuid:'sb',
Menuname:'subprogram',
Children:[ {
Menuid:'cb',
Menuname:'childprogram'
} ]
} ]
}, {
Menuid:'Pg2',
Menuname:'mainprogram2'
} ]
getting menu code
exports.getMenus = (req, res, next) => {
// need clarification
}
model for menu
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const menuSchema = mongoose.Schema({
menuId: {
type: String,
required: true,
unique: true
},
menuName: {
type: String,
required: true
},
icon: {
type: String,
required: false
},
type: {
type: String,
required: false
},
url: {
type: String,
required: false
},
levelId: {
type: Number,
required: true
},
programId: {
type: String,
required: false
},
order: {
type: Number,
required: true
},
createdBy: {
type: String,
require: false
},
createdDate: {
type: Date,
require: false,
},
updatedBy: {
type: String,
default: '',
require: false
},
updatedDate: {
type: Date,
default: '',
require: false,
},
});
menuSchema.plugin(uniqueValidator);
module.exports = mongoose.model('Menu', menuSchema);
router:
router.get('/getmenus/:id', MenuController.getMenus);
user request from client like
http://localhost:3000/api/menu/getmenus/pg
getmenus after slash word is a required menus under submenus
Note: if each data has order menans based on menu object need to render with that order. Please provide any solution.
Refer below link
your expected behaviour will be available in this graphlookup
https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/

How to select a value from an array in mongoose schema

Using MongoDb version 3.2.7
I have a mongoose schema like this which has an array of stock in branch schema. I want to select a subCategoryId in stock array and get the currentPrice of that subCategoryId only, for that I am using query
var getCriteria = { "stock.subCategoryId": subCategoryId }
var update = { "stock.$.currentPrice": currentPrice }
This query works for me at the time of updating the value as I am able to update the currentPrice of selected subCategoryId perfectly. But when I want to get a price of particular subCategoryId the following query gets me all the stocks in the branch collection. The query I am using is this:
var getCriteria ={ "stock.subCategoryId": subCategoryId }
Mongoose Schema
var branch = new Schema({
branchName: { type: String, trim: true, index: true, default: null },
isBlocked: { type: Boolean, default: false, required: true },
email: { type: String, trim: true, required: true, unique: true, index: true },
password: { type: String, required:true },
accessToken: { type: String, trim: true, index: true, unique: true, sparse: true },
stock: [stock],
});
var stock = new Schema({
categoryId: { type:Schema.ObjectId, ref: "categoies", default: null },
subCategoryId: { type:Schema.ObjectId, ref: "subCategories", default: null },
currentPrice: { type: Number },
isBlocked: { type: Boolean, default: false, required: true },
Date: { type: Date, default: Date.now, required: true }
});
To retrieve only the matching array element try this:
branch.find(getCriteria,{'stock.$' : 1},function(err,branch){...});
stock.$ will help you to retrieve only the matched element from the array.

Populating field values for referred documents in aggregate call in Mongoose

I have two base schemas User and Course
//User Model
var UserSchema = new Schema({
userId: {
type: String,
default: '',
required: 'Please provide UserId.',
index : true
},
Name :{
type: String,
default: '',
trim : true
}
});
//Course Schema
var CourseSchema = new Schema({
title: {
type: String,
default: '',
required: 'Please fill course title',
trim: true,
index: true
},
description: {
type: String,
default: '',
trim: true
},
category: {
type: String,
ref: 'Category',
index: true
}
});
And a UserCourseProgress schema for storing each user's course progress.
var UserCourseProgress= new Schema({
userId: {
type: String,
ref:'User',
required: 'Please provide the User Id',
index:true
},
courseid: {
type: Schema.Types.ObjectId,
ref: 'Course',
required: 'Please provide the Course Id',
index: true
},
timespent: {
type: Number, //seconds
default: 0
},
score: {
type: Number
}
});
Now I have to aggregate results such over UserCourseProgress schema on Course level such that i show my result like this :
- {Course Name}( {No_Of_Users_taken_Course} ) [e.g. Course A (15) ]
History.aggregate([{
$group: {"_id": {"primary": "$courseid"},
"popularityCount": {$sum: 1}}},
{$sort:{"popularityCount":-1}},
{$project:{"_id":0,
"courseid":"$_id.primary",
"count":1}}
])
Now want to populate Course title from Course Schema through its reference, but after going through the list of aggregation operators(here).I am not able to figure out a way to do so.
Can you suggest any way to populate data from other collections ??

Mongoose, index locations array

I have an array of locations in a document and I want to add a 2dSpere index on that array. Is that possible?
var LocationSchema = new Schema({
type: { type: String, required: true },
geometry: {
type: { type: String, required: true },
coordinates: { type: Array, required: true}
},
properties: Schema.Types.Mixed
});
// Collection to hold users
var UserSchema = new Schema({
username: { type: String, required: true, unique: true },
locations: [LocationSchema]
},{
versionKey: false
}
);
How do I add a 2DSphere index on the geometry field in the locations array?
https://github.com/LearnBoost/mongoose/blob/master/examples/geospatial/geoJSONSchema.js#L19
LocationSchema.index({ 'geometry' : '2dsphere' });
If you store values for location as 2 numbers in array, then your index would look like:
coordinates: { type: [Number], index: '2dsphere', required: true }
Although you need to create such index in your database:
db.users.ensureIndex({ 'locations.geometry.coordinates': '2dsphere' });

Resources