how to create a mongoose model with list of dictionaries? - node.js

I am trying to create a model for a collection whose objects look like below,how do declare clonedChangesdetailslist in mongoose which is a list of dictionaries?[String] doesn't seem to be the right thing?
{
"_id" : ObjectId("6d17d2dd84d4734eea82989f"),
"orgChange" : "62369696",
"created_on" : ISODate("2019-06-29T14:06:20.686Z"),
"clonedChangesdetailslist" : [
{
"clonedChange" : "62392779",
"clonedStatus" : "PASS",
"clonedChangeFinalStatus" : "PASS",
"updatedFailedReason" : "N/A",
"clonedChangeFinalStatusReason" : "N/A",
"updateStatus" : "PASS",
"clonedStatusfailReason" : "N/A"
},
{
"clonedChange" : "62392793",
"clonedStatus" : "PASS",
"clonedChangeFinalStatus" : "PASS",
"updatedFailedReason" : "N/A",
"clonedChangeFinalStatusReason" : "N/A",
"updateStatus" : "PASS",
"clonedStatusfailReason" : "N/A"
}
]
}
mongodb model
const mongoose = require('mongoose');
const { Schema } = require('mongoose');
const change_cloning_Schema= new Schema({
orgChange: String,
created_on: String,
clonedChangesdetailslist:[String]
},
{
collection: 'change_cloning',
timestamps: { createdAt: true, updatedAt: true },
});
module.exports = mongoose.model('change_cloning', change_cloning_Schema);

You can define clonedChangesdetailslist as an Array of Objects.
Try this :
const change_cloning_Schema= new Schema({
orgChange: String,
created_on: String,
clonedChangesdetailslist:[{
clonedChange : String,
clonedStatus : String,
clonedChangeFinalStatus : String,
updatedFailedReason : String,
clonedChangeFinalStatusReason : String,
updateStatus : String,
clonedStatusfailReason : String
}]
},
{
collection: 'change_cloning',
timestamps: { createdAt: true, updatedAt: true },
});

Related

How to update Reference Array in mongoose

I have a Group Collection, which is having a Reference array of Members. Two Objects are inter-connected like follow. When I am adding new members to the group the members field of Group object needed to be updated. How can I do this with a mongoose update operator.
var MemberSchema = new Schema({
name:{
type:String,
default:null
},
user_id:{
type : Schema.ObjectId,
ref : 'User',
default : null
}
});
var GroupSchema = new Schema({
name:{
type:String,
default:null
},
description:{
type:String,
default:null
},
members:[MemberSchema],
},{collection:"groups"});
Thank You in advance.
Update
I added a sample document of group.
{
"_id" : ObjectId("586a2e694467c41218b302c3"),
"members" : [
{
"_id" : ObjectId("586a2e694467c41218b302c6"),
"user_id" : ObjectId("58171d75e72bf516f92dcd4e"),
"name" : "Lakmal Kapukotuwa"
},
{
"_id" : ObjectId("586a2e694467c41218b302c5"),
"user_id" : ObjectId("5821807516325e127f59438e"),
"name" : "Prasad Perera"
},
{
"_id" : ObjectId("586a2e694467c41218b302c4"),
"user_id" : ObjectId("586263515356e908de6c899a"),
"name" : "Sadun Prasad"
}
],
"description" : "Des 1",
"name" : "My group",
"__v" : 0
}
If you are sending the new members as a list of objects with the following structure e.g.
membersListToAdd = [
{
"user_id": "58171d75e72bf516f92dcd4e",
"name": "foo"
},
{
"user_id": "5821807516325e127f59438e",
"name": "bar"
}
]
then use $push with $each modifier in an update as follows:
var query = { name: 'My Group' },
options = {},
callback = function (err, result) { console.log(result); };
Group.update(query, { $push: { members: { $each: membersListToAdd } } }, options, callback)
You are doing this wrong,
no need to have links in both collections and no need to nest models
try this instead
var Group = mongoose.model("Group", new Schema({
name: {
type:String
},
description: {
type:String
},
}));
Group.virtual("users", {
ref: "User",
localField: "_id",
foreignField: "groups"
});
var User = mongoose.model("User", new Schema({
name:{
type:String
},
groups: [{
type : Schema.ObjectId,
ref : 'Group'
}]
}));

Mongoose populate() returns empty array with no errors

I've been trying to get this populate thing to work, but I'm getting issues because I am not getting the expected results, and no errors to work with. Just simply an empty array.
My models look like this. Each their own file
var mongoose = require( 'mongoose' );
var upgradeSchema = new mongoose.Schema({
type: {
type: String,
default: "Any"
},
ability: String,
ability_desc: String,
level: Number,
tag: String
});
mongoose.model('Upgrade', upgradeSchema);
and the other
var mongoose = require( 'mongoose' );
var crypto = require('crypto');
var jwt = require('jsonwebtoken');
var userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true
},
hero: {
level: Number,
name: String,
type: {
path: String,
heroType: String
},
upgrades: [{
type: mongoose.Schema.Types.ObjectId, ref: 'Upgrade'
}],
unspent_xp: Number,
total_xp: Number,
},
armyTotal: {
type: Number,
default: 0,
max: 5000
},
army:[{
foc_slot: String,
unit_name: String,
unit_cost: Number
}],
username: {
type: String,
required: true,
unique: true,
},
faction: String,
name: {
type: String,
required: true
},
hash: String,
salt: String,
roles: {
type: String,
default: 'player' }
});
And I'm trying to do this
module.exports.profileRead = function(req, res) {
User
.findById(req.payload._id)
.populate('hero.upgrades')
.exec(function (err, user) {
if (err){
console.log(err);
} else {
res.status(200).json(user);
console.log("success");
}
});
}
};
This is an example of a user
{
"_id" : ObjectId("57b4b56ea03757e12c94826e"),
"hash" : "76",
"salt" : "2",
"hero" : {
"upgrades" : [
"57b42773f7cac42a21fb03f9"
],
"total_xp" : 0,
"unspent_xp" : 0,
"type" : {
"heroType" : "Psyker",
"path" : ""
},
"name" : "Jon Doe"
},
"username" : "michaelzmyers",
"faction" : "Grey Knights",
"email" : "email#gmail.com",
"name" : "Michael Myers",
"roles" : "player",
"army" : [],
"armyTotal" : 625,
"__v" : 3
}
Now, I've tried an array of just the strings with ObjectId's in them, similar to the eample, and I've also tried using ObjectId("STRINGHERE") and no luck. They both return just an empty array. However, if i get rid of the populate call (or change the contents inside populate from hero.upgrades to just hero, or upgrades) then it just returns an array of strings. I feel like the problem is with populate and how I'm using it. HOWEVER, when I had just a single upgrade in my databse (the test upgrade), everything worked fine. Now nothing works. Any thoughts? I'd be happy to provide more code if needed.
I found that during my little research that it will work:
User
.findById(req.payload._id)
.populate({
path: 'hero.upgrades',
model: 'Upgrade'
})
.exec(function (err, user) {
if (err){
console.log(err);
} else {
res.status(200).json(user);
console.log("success");
}
});
}
It looks like when user is giving nested object notation i.e. hero.upgrades into populate method, Mongoose got problems with detecting referring model.

mongoose: update field, push object in array [duplicate]

This question already has answers here:
Stop Mongoose from creating _id property for sub-document array items
(7 answers)
Closed 7 years ago.
I would like to add an element in an array in a mongo database:
db.keypairs.update( {pubkey: "1234567890"}, { $push: {listTxId: {txHash: "yyy", spent: false} } } )
The result is perfect:
listTxId" : [ { "txHash" : "xxx", "spent" : true },{ "txHash" : "yyy", "spent" : false } ]
Now I would like to do the same with node.js and mongoose
var res = wait.forMethod(Keypair,'update', {pubkey: "1234567890"}, { $push: { "listTxId": {"txHash":"zzz", "spent":false} } } );
Keypair is my node.js model for the mongoose collection:
var Keypair = require('./app/models/Keypair');
and wait.forMethod comes from a node module:
var wait = require('wait.for');
In the result, I have this "_id" element :
{ "txHash" : "zzz", "spent" : false, "_id" : ObjectId("56561571fea5d9a10a5771fd") }
QUESTION: where this ObjectId come from ? How can I get rid of it ?
UPDATE: mongoose schema:
var keypairSchema = mongoose.Schema({
userId : { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
pubkey : String,
privkeyWIF : String, // temp
balance : Number,
listTxId : [{
txHash : String,
spent : Boolean
}],
walletId : { type: mongoose.Schema.Types.ObjectId, ref: 'Wallet' },
description : { type: String, maxlength: 40 },
comments : String,
isMasterKey : { type: Boolean, default: false },
date : Date
});
Mongoose will put ids in your subdocument arrays. listTxId is a subdocument array. You can add _id: false to your schema to prevent this:
var keypairSchema = mongoose.Schema({
userId : { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
pubkey : String,
privkeyWIF : String, // temp
balance : Number,
listTxId : [{
_id: false,
txHash : String,
spent : Boolean
}],
walletId : { type: mongoose.Schema.Types.ObjectId, ref: 'Wallet' },
description : { type: String, maxlength: 40 },
comments : String,
isMasterKey : { type: Boolean, default: false },
date : Date
});

Can't get mongoose 'populate' to work

I am stuck on populating a ref field in a simple mongoose (3.8.8) query.
It's probably a stupid issue but i can't actually sort it out..
var Schema = mongoose.Schema;
var ItemSchema = new Schema({
description: { type: String },
comments: [ { type:Schema.Types.ObjectId, ref:'Comment'} ],
created: { type: Date, default: Date.now }
});
var Item = mongoose.model('Item', ItemSchema);
var CommentSchema = new Schema({
text: { type: String },
item_id: { type:Schema.Types.ObjectId, ref:'Item'} ,
created: { type: Date, default: Date.now }
});
var Comment = mongoose.model('Comment', CommentSchema);
Item.find().populate('comments').exec(function(err,item){
console.log('Item ',item)
})
the data is:
/* item0 */
{
"_id" : ObjectId("53da00cc5ddd29442463e716"),
"description" : "item1",
"created" : ISODate("2014-07-31T08:39:40.475Z"),
"comments" : [],
"__v" : 0
}
/* item1 */
{
"_id" : ObjectId("53da00cc5ddd29442463e717"),
"description" : "item2",
"created" : ISODate("2014-07-31T08:39:40.478Z"),
"comments" : [],
"__v" : 0
}
/* comment0 */
{
"_id" : ObjectId("53da01e9ef4ecaa0231fdc8d"),
"item_id" : ObjectId("53da00cc5ddd29442463e716"),
"text" : "comment1",
"created" : ISODate("2014-07-31T08:44:25.768Z"),
"__v" : 0
}
It just won't work as expected, not populating the 'comments' array, tho in my comments collection the item_id is populated correctly.
What's the problem?
Thanks in advance

geospatial queries on subdocuments

I have a mongoose schema with subdocuments that contain a location field (with 2dSpehre index). Like this:
var playerSchema = new mongoose.Schema({
name: { type: String, required: true },
addresses: [
{
address: {
street: String,
city: String,
zip: String,
country: String
},
loc: { type: [Number], index: '2dSphere' }
}
],
});
When I try to query for addresses via geospatial operators I get this error: planner returned error: unable to find index for $geoNear query. The query looks like this:
var query = {
'addresses.loc': {
$nearSphere: {
$geometry: { type: 'Point', coordinates: [16.3738189, 48.2081743] }
}
}
};
Player.find(query).exec();
I also checked via mongo that the index really exists:
> db.player.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "project.player"
},
{
"v" : 1,
"key" : {
"addresses.loc" : "2dsphere"
},
"name" : "addresses.loc_2dsphere",
"ns" : "project.player",
"2dsphereIndexVersion" : 2
}
]
What am I doing wrong? Thanks in advance.
Are you sure you are using the right collection? Mongoose will pluralize your collection name by default (so players instead of player).
The script below is working for me. For some reason Mongoose wasn't creating the 2dsphere index for me when it was specified in the schema so I moved that out.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var playerSchema = new mongoose.Schema({
name: { type: String, required: true },
addresses: [
{
address: {
street: String,
city: String,
zip: String,
country: String
},
loc: { 'type': { type: String }, 'coordinates': { type: [Number] } }
}
],
});
playerSchema.index({'addresses.loc': '2dsphere'});
var Player = mongoose.model('Player', playerSchema);
mongoose.connect('mongodb://localhost/test');
var query = Player.find({
'addresses.loc': {
$nearSphere: {
$geometry: { type: 'Point', coordinates: [16.3738189, 48.2081743] }
}
}
}, function (err, players) {
console.log(err)
console.log(players)
});

Resources