How to get index name from object with mongoose - node.js

I have some objects in Mongodb created according to this mongoose Schema
const MetalSchema = mongoose.Schema({
dia_6:{type:Number},
dia_8:{type:Number},
dia_10:{type:Number},
dia_12:{type:Number},
dia_15:{type:Number}
});
All Objects have different quantity of key:value pairs. How to get the key names which are present in Object in DB?

i think you can use something like this
MetalSchema.schema.eachPath(function(path) {
console.log(path);
});

I got index names with this code:
var mykeys;
database.findOne({}, function(result) {
mykeys = Object.keys(result._doc);
});
Great thank's for STR for his answer in neighber question

Related

unable to find subdocument using mongoose

I wanted to find the subdocument with id and return the subdocument, not the parent document, my schema are as follows :
var coursesSchema = new mongoose.Schema({
coursename:{type:String}
});
var parentSchema = new mongoose.Schema({
courses:[coursesSchema]
});
var Parent= mongoose.model('parent', parentSchema );
module.exports = Parent;
let data = Parent.courses.id(_id);
as given in the docs I tried to find the subdocument using .id, it is throwing error saying Cannot read property 'id' of undefined,
and after searching a lot found this question I tried the same, apparently it also returned the same error.
let data = Parent['courses'].id(_id);
please help me with this, I am not able to get my head around with it๐Ÿ™
In order to get the subdocument, you have to do the following:
Look for the document
Reference the subdocument property
In your case, you have defined a Model. Based on this model, you would need to:
Parent.findOne({ _id: ObjectId("abcd12345678901234567890") }, function(err, doc) {
let subDocument = doc.courses;
...
}
The reason you get the "undefined" error is because the courses subdocument doesn't have a field called id. It only has a field called coursename.
We can solve this using Aggregation operations as #KunalMukherjee pointed out in the comments Here is a quick example to do so

How to get all keys + in a collection + mongodb +mongoose

I want to get all distinct keys from a collections in mongoDB.
I refereed the following links:
Get names of all keys in the collection
Querying for a list of all distinct fields in MongoDB collection and etc.
But still i didn't get the right solution...
As i am using mongoose in the first link reference syas runCommand is not a function.
As findOne() will give the first document keys alone but i need all distnct keys
userModel.findOne(condition, projection, callback)
Please share your ideas..
If you are using Mongoose 3.x, then you can try this :
userModel.find().distinct('_id', function(error, ids) {
// ids is an array of all ObjectIds
});
Or you can find all the documents and extract key from that like :
var keys = {};
var docKeys = [];
userModel.find({}, function(err, allDocs){
allDocs.forEach(function(doc){
docKeys = Object.keys(doc);
docKeys.forEach(function(docKey){
if(!keys[docKey]) keys[docKey] = true;
})
})
})
I have just written for getting logic, you can change according to your requirements and efficiency
Try like this you will get all of your keys defined into your mongoose model/Schema.
import Model from 'your_model_path'
for(let property in Model.schema.obj){
console.log("key=====>",property);
}

find id of latest subdocument inserted in mongoose

i have a model schema as :
var A = new Schema ({
a: String,
b : [ { ba: Integer, bb: String } ]
}, { collection: 'a' } );
then
var M = mongoose.model("a", A);
var saveid = null;
var m = new M({a:"Hello"});
m.save(function(err,model){
saveid = model.id;
}); // say m get the id as "1"
then
m['b'].push({ba:235,bb:"World"});
m.save(function(err,model){
console.log(model.id); //this will print 1, that is the id of the main Document only.
//here i want to find the id of the subdocument i have just created by push
});
So my question is how to find the id of the subdocument just pushed in one field of the model.
I've been looking for this answer as well, and I'm not sure that I like accessing the last document of the array. I do have an alternative solution, however. The method m['b'].push will return an integer, 1 or 0 - I'm assuming that is based off the success of the push (in terms of validation). However, in order to get access to the subdocument, and particularly the _id of the subdocument - you should use the create method first, then push.
The code is as follows:
var subdoc = m['b'].create({ ba: 234, bb: "World" });
m['b'].push(subdoc);
console.log(subdoc._id);
m.save(function(err, model) { console.log(arguments); });
What is happening is that when you pass in the object to either the push or the create method, the Schema cast occurs immediately (including things like validation and type casting) - this means that this is the time that the ObjectId is created; not when the model is saved back to Mongo. In fact, mongo does not automatically assign _id values to subdocuments this is a mongoose feature. Mongoose create is documented here: create docs
You should also note therefore, that even though you have a subdocument _id - it is not yet in Mongo until you save it, so be weary of any DOCRef action that you might take.
The question is "a bit" old, but what I do in this kind of situation is generate the subdocument's id before inserting it.
var subDocument = {
_id: mongoose.Types.ObjectId(),
ba:235,
bb:"World"
};
m['b'].push(subDocument);
m.save(function(err,model){
// I already know the id!
console.log(subDocument._id);
});
This way, even if there are other database operations between the save and the callback, it won't affect the id already created.
Mongoose will automatically create an _id for each new sub document, but - as far as I know - doesn't return this when you save it.
So you need to get it manually. The save method will return the saved document, including the subdocs. As you're using push you know it will be the last item in the array, so you can access it from there.
Something like this should do the trick.
m['b'].push({ba:235,bb:"World"});
m.save(function(err,model){
// model.b is the array of sub documents
console.log(model.b[model.b.length-1].id);
});
If you have a separate schema for your subdocument, then you can create the new subdocument from a model before you push it on to your parent document and it will have an ID:
var bSchema = new mongoose.Schema({
ba: Integer,
bb: String
};
var a = new mongoose.Schema({
a: String,
b : [ bSchema ]
});
var bModel = mongoose.model('b', bSchema);
var subdoc = new bModel({
ba: 5,
bb: "hello"
});
console.log(subdoc._id); // Voila!
Later you can add it to your parent document:
m['b'].push(subdoc)
m.save(...

Can you define instance method for sub documents in Mongoose?

If I have a a Schema in Mongoose that's defined like:
var subSchema = new Schema({
some: String
});
var topSchema = new Schema({
subs: [subSchema]
});
var topModel = mongoose.model("Top", topSchema);
Is it possible to define an instance method for the sub document? I've tried the following(added before the model declaration), but it doesn't work:
subSchema.methods.someFn = function() {
return 'blah';
};
Answering my own question.
What I originally wanted to do was to create a function that can be used on the collection of subdocs, as in:
topdoc.subs.someFn();
However, what I actually did with code in the original question was create a function for a subdoc itself, as in:
topdoc.subs[i].someFn();
This works.
As far as I can tell, creating a function for the collection of subdocs is not supported by Mongoose.
I got around this by defining a method in topSchema that would do what I want.

Nested models mongoose with nodejs generates duplicates

here is my code for models.js where I keep models
var mongoose = require('mongoose')
, Schema = mongoose.Schema;
var GroupSchema = new Schema({
title : String
, elements : [ElementSchema]
, author : String
});
var ElementSchema = new Schema({
date_added : Date
, text : String
, author : String
});
mongoose.model('Group', GroupSchema);
exports.Group = function(db) {return db.model('Group');};
mongoose.model('Element', ElementSchema);
exports.Element = function(db) { return db.model('Element');
};
To me it looks pretty clear, but when I do
function post_element(req, res, next) {
Group.findOne({_id: req.body.group}, function(err, group) {
new_element = new Element({author: req.body.author,
date_added: new Date()});
new_element.save();
group.elements.push(new_element);
group.save();
res.send(new_element);
return next();
})
}
I don't understand why when I go in Mongo I have two collections one called Groups with nested groups (so it looks fine) and the other collection is called Elements.
Why? Shouldn't it be called just Group ?
I don't understand, a good chap that please explain it to me?
Thanks,
g
When you execute this line:
new_element.save();
you're saving the newly created element to the Elements collection. Don't call save on the element and I think you'll get the behavior you're looking for.
Its because of the following line:
mongoose.model('Element', ElementSchema);
This registers a model in mongoose and when you register a model, it will create its own collection inside mongo. All you have to do is get rid of this line and you will see it disappear.
On another note, its much cleaner and easier to setup your files to only export one model per file using the following to export the model:
module.exports = mongoose.model('Group', GroupSchema);
Hope this helps!

Resources