associative array does not save mongoose - node.js

tournament.js
var mongoose = require('mongoose');
var TournamentPlayer = require('../models/tournamentPlayer');
var SportPlayer = require('../models/sportPlayer');
var Schema = mongoose.Schema;
var TournamentSchema = new Schema({
tournamentPlayers:[{
type: Schema.Types.Mixed,
ref: 'TournamentPlayer'
}],
buyin: Number,
entrants: Number,
prizePool: Number,
name: String,
sport: String,
endOfRegistration:Date,
sportsPlayers:[{
type: Schema.Types.Mixed,
ref: 'SportPlayer'
}],
created: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('Tournament', TournamentSchema);
api.js
tournament.tournamentPlayers[player.userId]=player;
console.log("ass array"+util.inspect(tournament.tournamentPlayers,false,null));
console.log("ass array element" + util.inspect(tournament.tournamentPlayers[player.userId] ,false,null));
console.log("ass array just in case"+util.inspect(tournament.tournamentPlayers,false,null));
tournament.tournamentPlayers.push(player);
console.log("push"+util.inspect(tournament.tournamentPlayers,false,null));
Output
ass array[]
ass array element{ username: 'batman',
roster:
{ __v: 0,
userId: '57bb89eb10c4b4ac124980b9',
tournamentId: '57d49f5169cc78ac21c5e791',
_id: '57d4b421315f1b501ad5456f',
playerRoster:
[ { _id: '57cfe922dcba0f295f57e26d', playerFirstName: 'Julio' },
{ _id: '57cfe939dcba0f295f57e274', playerFirstName: 'Odell' } ] },
rank: 'blah',
totalPoints: 0,
userId: '57bb89eb10c4b4ac124980b9',
_id: '57d4b421315f1b501ad54570' }
ass array just in case[]
push[{"username":"batman","roster":{"__v":0,"userId":"57bb89eb10c4b4ac124980b9","tournamentId":"57d49f5169cc78ac21c5e791","_id":"57d4b421315f1b501ad5456f","playerRoster":[{"_id":"57cfe922dcba0f295f57e26d","playerFirstName":"Julio"},{"_id":"57cfe939dcba0f295f57e274","playerFirstName":"Odell"}]},"rank":"blah","totalPoints":0,"userId":"57bb89eb10c4b4ac124980b9","_id":"57d4b421315f1b501ad54570"}]
I am trying to declare and add objects to an associative array. When I look them up, I want to use userId instead of _id. When trying with this code, the object can be called directly tournamentPlayers[userId], but doesn't display as part of the array tournamentPlayers. When I do a regular push, it displays, but this isn't what I want. I am able to use the object, but can't save it through mongoose.
I've seen a couple of questions but they did not answer this. The second answer here has strict: false as a setting, but not for a single schema element.
Mongoose: Saving as associative array of subdocuments vs array of subdocuments
How can I declare and add objects to an associative array in mongoose?

Related

Mongoose array of objects are empty when saved

I am trying to save an array of objects to mongoose but this saves only an empty array in database. The below is model and schema
const HoldingSchema = new Schema({ symbol: String, quantity: Number });
const UserSchema = new Schema({
_id: {
type: String,
required: true,
},
holdings: {
type: [HoldingSchema],
default: undefined,
},
});
const UserModel = mongoose.model('Users', UserSchema, 'Users');
I try to store an array of objects with the below code. But this creates an empty array in the place of holding.
const testuser = new userModel({
_id: '001',
holding: [{ symbol: 'itc', quantity: 100 }],
});
await testuser.save(); // creates { _id: '001', holdings: [], __v: 0 }
Is it not possible to store array of custom objects. If not what would be an alternative?
There is actually a typo in your code that is why it doesn't save your holdings.
You have written holding, while the field is actually holdings
const testuser = new userModel({
_id: '001',
holdings: [{ symbol: 'itc', quantity: 100 }],
});

Find Object and Update by pushing to nested Array in MongoDb

I have created a Mongoose Model which holds nested arrays exercises>history>data. I want to make a put request and push an Object, consisting of the time the data was createdAt as well as an array of the Users data to the history of the exercise that was run. However, the following attempt did not work:
User.findOneAndUpdate(
{ _id: req.user.id, "exercises.title": req.body.exercise_title },
{ $push: { "exercises.$.history": { data: [1,2,3,4,5] } } }
);
My Schema looks as follows:
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
userName:{
type: String,
required: true},
exercises:[{
title:{
type: String,
},
history: [{
createdAt: {
type: Date,
default: Date.now
},
data: []
}]
}]
});
module.exports = mongoose.model('User', UserSchema)
I have no clue why my query is not working

Match specific value in mongoose populate

Following is the schema of a user collection:
const Mongoose = require('mongoose')
const Schema = Mongoose.Schema
const userSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String
},
supporterOf: [{
type: Schema.Types.ObjectId,
ref: 'individual',
required: false
}],
})
module.exports = Mongoose.model('user', userSchema);
I want to populate 'supporterOf' which is a collection of individual (ref: individual).
The 'supporterOf' contains an array of ObjectId.
I am having the problem of matching the specific objectId with that ObjectId array.
Can anyone suggest me how I can match specific ObjectId with an array of ObjectIds in populate function?
You have a reference of 'individual' in supporterOf and you want to populate only relevant object from the array of individuals?
If this is right case then do the following:
YourUserModel.findById(userId, function (err, user) {
console.log(user)
}).populate({
path: 'supporterOf',
match: {
yourObjectOfIndividualDocument: yourMatchingIdOfIndividual
}
})
.exec()
Replace yourObjectOfIndividualDocument: yourMatchingIdOfIndividual by name: 'abcd'.
Here name is the field of Individual document not of User document.
You add condition in populate
if you wanted to populate fans array based on their age, and return, at most, any 5 of them
.populate('fans', null, { age: { $gte: 21 }}, { limit: 5 })

Mongoose populate a field without ObjectId?

I have a schema:
var Schema = mongoose.Schema;
var TicketSchema = new Schema({
externalId: String,
name: String,
items: [{
externalId: String,
price: Number,
quantity: {
type: Number,
default: 1
},
comment: {
type: String,
default: '',
trim: true
},
entity: {
type: String,
ref: 'Entity'
}
}],
tableId: String
});
mongoose.model('Ticket', TicketSchema);
And I want to populate entity field with an unique field other than ObjectId.
How can I achieve that?
Though late answer. Please check Populate Virtuals for Mongoose 4.5.0
Click the link below
http://mongoosejs.com/docs/populate.html
And scroll down or search for Populate Virtuals you will see it does exactly what you want.
I found Views as one useful approach, though not sure it is the most efficient! For example, in movielens database, I wanted to refer 'movieId' in ratings collection to 'movieId' in the movies collection using 'movieId' as foreign key.
db.createView('rating-movie-view','ratings',[{$lookup:{from:"movies",localField:"movieId",foreignField:"movieId",as:"ratings_movie"}},{ $project:{'userId':1,'movieId':1,'rating':1,'timestamp':1,'ratings_movie.title':1,'ratings_movie.genres':1 } }])
New view "rating-movie-view" thus created has the required fields 'title and 'genres'.
db["rating-movie-view"].findOne()
{
"_id" : ObjectId("598747c28198f78eef1de7a3"),
"userId" : 1,
"movieId" : 1129,
"rating" : 2,
"timestamp" : 1260759185,
"ratings_movie" : [
{
"title" : "Escape from New York (1981)",
"genres" : "Action|Adventure|Sci-Fi|Thriller"
}
]
}
Hope this useful!
Those who are not familiar with movielens data here are the schema
var MovieSchema = new mongoose.Schema({
movieId: Number,
title: String,
genres: String,
});
var RatingSchema = new mongoose.Schema({
userid: Number,
movieId:Number,
rating: Number,
timestamp:Number,
});
//View schema
var RatingViewSchema = new mongoose.Schema({
userid: Number,
movieId:Number,
rating: Number,
timestamp:Number,
rating_movie:{title:String,genres:String}
});
const blogs = this.blogModel
.find(find)
.populate('blogCategory', 'name -_id');
Note -_id will exclude the object _id
I'm not sure if I understood your question correctly.
In Mongoose model, in case we do not specify a primary key, it automatically adds in an extra field called ObjectId and assigns a unique value for each object.
In case we need to specify our own key, we can do it by specifying the key property.
For example:
mongoose.model('Todo', {
todoID: {
type: String,
key: true
},
text: {
type: 'text'
},
done: {
type: Boolean,
default: false,
},
date: {
type: Date,
},
items: [{
entity: {
type: String,
ref: 'Entity'
}
}]
});
I hope, this is what you meant.
If you are asking about fetching objects based on Items -> entity's property,
Todo.find({'items.entity.type':required_type}, function(err, foundTodos){
// ---
});
Thanks,
Use crypto to hash something unique like the objectId , and then save it to your entities.
Var hash = crypto.createHmac('sha256', ticket.objectId).digest('hex');
Ticket.entities= hash;

Mongoose Relationship Populate Doesn't Return results

var SecuritySchema = new Mongoose.Schema({
_bids: [{
type: Mongoose.Schema.Types.ObjectId,
ref: 'BuyOrder'
}],
_asks: [{
type: Mongoose.Schema.Types.ObjectId,
ref: 'SellOrder'
}]
});
var OrdersSchema = new Mongoose.Schema({
_security: {
type: Mongoose.Schema.Types.ObjectId,
ref: 'Security'
},
price: {
type: Number,
required: true
},
quantity: {
type: Number,
required: true
}
});
// declare seat covers here too
var models = {
Security: Mongoose.model('Security', SecuritySchema),
BuyOrder: Mongoose.model('BuyOrder', OrdersSchema),
SellOrder: Mongoose.model('SellOrder', OrdersSchema)
};
return models;
And than when I save a new BuyOrder for example:
// I put the 'id' of the security: order.__security = security._id on the client-side
var order = new models.BuyOrder(req.body.order);
order.save(function(err) {
if (err) return console.log(err);
});
And attempt to re-retrieve the associated security:
models.Security.findById(req.params.id).populate({
path: '_bids'
}).exec(function(err, security) {
// the '_bids' array is empty.
});
I think this is some sort of naming issue, but I'm not sure, I've seen examples here and on the moongoose website that use Number as the Id type: http://mongoosejs.com/docs/populate.html
The ref field should use the singular model name
Also, just do:
models.Security.findById(req.params.id).populate('_bids').exec(...
My main suspicion given your snippet at the moment is your req.body.order has _security as a string instead of an array containing a string.
Also, you don't need an id property. Mongodb itself will automatically do the _id as a real BSON ObjectId, and mongoose will add id as a string representation of the same value, so don't worry about that.
While I don't understand your schema (and the circular nature of it?), this code works:
var order = new models.BuyOrder({ price: 100, quantity: 5});
order.save(function(err, orderDoc) {
var security = new models.Security();
security._bids.push(orderDoc);
security.save(function(err, doc) {
models.Security.findById({ _id: doc._id })
.populate("_bids").exec(function(err, security) {
console.log(security);
});
});
});
It:
creates a BuyOrder
saves it
creates a Security
adds to the array of _bids the new orderDoc's _id
saves it
searches for the match and populates
Note that there's not an automatic method for adding the document to the array of _bids, so I've done that manually.
Results:
{ _id: 5224e73af7c90a2017000002,
__v: 0,
_asks: [],
_bids: [ { price: 100,
quantity: 5,
_id: 5224e72ef7c90a2017000001, __v: 0 } ] }

Resources