Why are mongoose query result objects so verbose in new version? - javascript

I installed my dependencies on a new computer and it must have updated mongoose.
All my informative results from queries have returned into these messes with a lot of information that may be useful at times but generally is not useful. Very verbose.
So for example when it runs console.log(result) in a query promise, it used to return something like this:
user: {
_id: '2c918aa5-3d5f-4397-8dd9-35c3675f53a2',
email: 'ayeman#gmail.com',
username: 'ayeman',
password: '$2b$10$1sBah/12s12Ox0971221nk5g2s12s11FVRCW',
watching: '',
__v: 0
}
instead now it returns this:
model {
'$__': InternalCache {
strictMode: true,
selected: {},
shardval: undefined,
.....
*200 plus lines of verbose data*
....
remove: [Function: pull],
_path: 'chats',
isMongooseArray: true,
validators: [],
_schema: [SchemaArray]
],
_id: '2c918aa5-3d5f-4397-8dd9-35c3675f53a2',
email: 'ayeman#gmail.com',
username: 'ayeman',
password: '$2b$10$1sBah/12s12Ox0971221nk5g2s12s11FVRCW',
watching: '',
__v: 0
},
'$init': true
}
I cant for the life of me find the documentation to return it to the old style.
It seems silly to find all my console logs and cut the extra data manually.
Is there a method to change this back? I was looking for something like mongoose.model.options.changeResultsStyle() or something but I cannot find anything

In the new mongoose version it seems as if it defaults to verbose results. Using .lean() on mongoose query methods will return the lean style that the old mongoose version defaulted too.
My example scenario
User.findOne({username: req.body.username }, {friends: 1}, function(err, result) {
if (err) throw err;
console.log(result.friends[1].pending)
res.json(result.friends[1].pending);
}).lean();
{
_id: '2c918aa5-3d5f-4397-8dd9-35c3675f53a2',
friends: [ { confirmed: [Array] }, { pending: [Array] } ],
status: 'offline',
chats: [ { confirmed: [Array] }, { pending: [Array] } ],
email: 'ayeman#gmail.com',
username: 'ayeman',
password: '$2b$10$gq0OrbxulaUBah/O.LhfjuiOx0970brivNStLXnk5gGn0QYRFVRCW',
watching: '',
__v: 0
}

Related

MongoDB: accessing current document for $push doesnt work

This is my query:
await Users.updateOne(
{ _id: user._id },
{
$set: {
'email.isVerified': false,
'email.current': null,
},
$push: {
'email.oldEmails': {
email: "$email.current",
isVerified: "$email.isVerified"
},
},
}
);
The document has the fields email.current and email.isVerified but it cant use them in the $push pipeline. The query works fine otherwise but why cant I use the reference to the current document with "$.fiel" in the $push operation?
As far as i know there is no order in the update operators, and your update depends on order.If you want order you can use pipeline updates with aggregate operators/stages (MongoDB >= 4.2)
Its your query just as pipeline, and with $concatArrays instead of $push
(i haven't tested the code)
await Users.updateOne(
{ _id: user._id },
[
{
$set: {
'email.oldEmails':
{ $concatArrays: [ '$email.oldEmails',[{
email: "$email.current",
isVerified: "$email.isVerified"
}] ] }
'email.isVerified': false,
'email.current': null,
},
])

Modyfing already avalable json file with faker

I have a json file which stores the data from mongodb in a array format i want to change some fields in it example email, phone number etc.How can i do it using nodejs and faker?
Exaple of one data.json file
{
_id: 54522,
roles: [ [Object] ],
__v: 48,
name: { last: 'Coke', first: 'Colay' },
cv: {
_id: 54522,
updatedAt: Z,
createdAt: 2Z,
educationEntries: [Array],
workEntries: [Array]
},
unverifiedEmail: null,
unverifiedPhoneNumber: null,
phoneNumberVerificationCode: null,
phoneNumber: '8754552512',
password: 'expected',
emailVerificationCode: 'null',
smoochUserId: '2b390',
},
I want to change phonenumber emailverification and unverfiedEmail entries.
Thanks in advance.

Sequelize .set error, .set is not a function

I am trying to set up a belongsTo and hasMany association which seems to be working, but when I run .set I am getting the error fighterData.setUsers is not a function. The dialect is mySql. Here is my code:
Fighters.belongsTo(Users)
Users.hasMany(Fighters);
Users.sync()
Fighters.sync()
//creates the table if it doesn't exist
const insertFighter = function(obj, sessId) {
return Fighters.create(obj, {returning: true}).then((fighterData) => {
//console.log('inserted a fighter \n', fighterData);
return Users.findOne({
where: {
id: sessId
}
}).then((userData) => {
//console.log('fighterData in findOne promise \n', fighterData)
return fighterData.setUsers(userData)
}).then((success)=> {
console.log('user fighter join success')
return
}).catch((err)=> {
console.log('user fighter join error \n', err)
return
})
}).catch((err)=> {
console.log('error inserting fighter \n', err);
})
}
The error that's logging is user fighter join error.
interestingly, userData.setFighters(fighterData) works successfully, but that is not what I need
EDIT
This is what fighterData is:
fighterData in findOne promise
Fighters {
dataValues:
{ id: 7,
name: 'Gilbert Burns',
image:
'https://www.sherdog.com/image_crop/200/300/_images/fighter/20140806063215_IMG_8432.JPG',
next_opponent: 'Kamaru Usman',
next_fight: 'July 11, 2020 ',
style: 'mma',
updatedAt: 2020-06-17T06:00:40.368Z,
createdAt: 2020-06-17T06:00:40.368Z },
_previousDataValues:
{ name: 'Gilbert Burns',
image:
'https://www.sherdog.com/image_crop/200/300/_images/fighter/20140806063215_IMG_8432.JPG',
next_opponent: 'Kamaru Usman',
next_fight: 'July 11, 2020 ',
style: 'mma',
id: 7,
createdAt: 2020-06-17T06:00:40.368Z,
updatedAt: 2020-06-17T06:00:40.368Z,
UserId: undefined },
_changed:
{ name: false,
image: false,
next_opponent: false,
next_fight: false,
style: false,
id: false,
createdAt: false,
updatedAt: false,
UserId: false },
_modelOptions:
{ timestamps: true,
validate: {},
freezeTableName: false,
underscored: false,
paranoid: false,
rejectOnEmpty: false,
whereCollection: null,
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [],
name: { plural: 'Fighters', singular: 'Fighter' },
omitNull: false,
sequelize:
Sequelize {
options: [Object],
config: [Object],
dialect: [MysqlDialect],
queryInterface: [QueryInterface],
models: [Object],
modelManager: [ModelManager],
connectionManager: [ConnectionManager],
importCache: {} },
hooks: {} },
_options:
{ isNewRecord: true,
_schema: null,
_schemaDelimiter: '',
attributes: undefined,
include: undefined,
raw: undefined,
silent: undefined },
isNewRecord: false }
This is returned from entering one fighter's information into the database.
The problem is with the naming of your models.
Sequelize expects your models to be named in singular form (User instead of Users), so it's getting confused with what it should name the generated setter and getter methods for your association.
If you try fighterData.setUser(userData) instead of fighterData.setUsers(userData), it should work.
If you you want to use setUsers instead, you will have to make adjustments to your model to tell Sequelize to use Users as the singular form of User:
Users.init({
sessId: Sequelize.STRING
}, {
sequelize: sequelize,
name: {
singular: 'users'
}
});
You can overwrite the plural form the same way as well.
You can read more about this here: Sequelize naming strategy

Mongoosejs .find returning whole model instead of document [duplicate]

This question already has answers here:
How do you turn a Mongoose document into a plain object?
(9 answers)
mongoose .find() method returns object with unwanted properties
(5 answers)
How can I display a JavaScript object?
(40 answers)
Model.findOne not returning docs but returning a wrapper object
(1 answer)
Closed 3 years ago.
I am running on .find() query on an existing model. I have used this code in the past and have changed nothing but now all of the sudden it's not working for some reason. I am thinking either MongoDB or MongooseJS updated and the functionality has changed.
var retrieve = function() {
Repo.find({}, function(err, docs) {
console.log(docs)
})
};
retrieve();
returns
[
model {
'$__': InternalCache {
strictMode: true,
selected: {},
shardval: undefined,
saveError: undefined,
validationError: undefined,
adhocPaths: undefined,
removing: undefined,
inserting: undefined,
version: undefined,
getters: {},
_id: 5e02e91c908f0f086e737189,
populate: undefined,
populated: undefined,
wasPopulated: false,
scope: undefined,
activePaths: [StateMachine],
pathsToScopes: {},
ownerDocument: undefined,
fullPath: undefined,
emitter: [EventEmitter],
'$options': true
},
isNew: false,
errors: undefined,
_doc: {
__v: 0,
stars: 2,
id: 1322,
url: 'url',
name: 'name',
_id: 5e02e91c908f0f086e737189
},
'$init': true
},
model {
'$__': InternalCache {
strictMode: true,
selected: {},
shardval: undefined,
saveError: undefined,
validationError: undefined,
adhocPaths: undefined,
removing: undefined,
inserting: undefined,
version: undefined,
getters: {},
_id: 5e02e92c3f6b72088246c563,
populate: undefined,
populated: undefined,
wasPopulated: false,
scope: undefined,
activePaths: [StateMachine],
pathsToScopes: {},
ownerDocument: undefined,
fullPath: undefined,
emitter: [EventEmitter],
'$options': true
},
isNew: false,
errors: undefined,
_doc: {
__v: 0,
stars: 2,
id: 2,
url: 'url1',
name: 'name1',
_id: 5e02e92c3f6b72088246c563
},
'$init': true
}
]
it should return
[{name: 'name', id: 2, url: 'url', stars: 2},
{name: 'name1', id: 1322, url: 'url1', stars: 2}]
I don't know why this is happening
---- edit for Ahsok ---
I tried using your code
const retrieve = () => {
Repo.find({})
.then(repo => {
console.log({ repo })
})
.catch(error => {
console.log({ error })
})
};
And it's still not returning what it needs to be. Now it's returning
{
repo: [
model {
'$__': [InternalCache],
isNew: false,
errors: undefined,
_doc: [Object],
'$init': true
},
model {
'$__': [InternalCache],
isNew: false,
errors: undefined,
_doc: [Object],
'$init': true
}
]
}
Which is the same thing it was returning above, just in a slightly different format
This is the expected behavior, Mongoose find query always return an instance of a mongoose i.e what you are getting. There are two ways to handle this:
Convert your response to plain Object on your own:
console.log(docs.toObject())
Let mongoose itself do this for you (Using lean):
Repo.find({}).lean().exec(function(err, docs) {
console.log(docs);
});
You can read more about lean here
Hope this helps :)
If you are using async function then use this syntax
const retrieve = async () => {
const repo = await Repo.find({})
console.log(repo)
};
If you have no idea whats going on up there use this syntax
const retrieve = () => {
Repo.find({})
.then(repo => {
console.log({ repo })
})
.catch(error => {
console.log({ error })
})
};
You can take and doc ride from here too.
Why this happens Because find return cursor or promise to retrieve _doc from it you need to use the promise.
Here the first type solution is popular to clean code.
I figured it out. Turned out I had to revert node to a previous version for this to be the default behavior. Using .lean() as Mohammed pointed out would have also worked but I wanted to know why my code was behaving differently than it used to and it turns out that it was caused by a node update.

Find documents that contain certain field for sub-object MongoDb and Node.js

I have a collection with the following format:
[
{
firstname: 'Joe',
lastname: 'Blow',
emails: [
{
email: 'test#example.com',
valid: false
},
{
email: 'test2#example.com',
valid: false
}
],
password: 'abc123',
_id: 57017e173915101e0ad5d94a
},
{
firstname: 'Johnny',
lastname: 'Doe',
emails: [
{
email: 'test3#example.com',
valid: false
}
],
password: 'abc123',
_id: 57017e173915101e0ad5d87b
},
]
I am trying to find a user based on the emails.email field. Here is what I have so far:
db.collection('users').aggregate([
{$unwind: "$emails"},
{$group: {_id: "$_id",user_emails: { $push: "$emails.email" } } },
{$match: {'user_emails': { $in: ['test#example.com'] } } }
],
(error, result) => {
console.log(error);
console.log(result);
}
);
When I run this command in the mongo shell it seems to work; however when I run it in Node.js it prints null for the error and [] for the result.
What am I doing wrong? I am pretty new to MongoDB and just can't seem to figure this out.
Why do you want to unwind the entire emails? That will be a very expensive operation when your collection grows with tons of records.
The below query will return the user with the email test2#example.com. I think thats what you are looking for right?
db.email.find({emails :{$elemMatch:{email:"test2#example.com"}}})
I have re-written your code with slight changes.
var col = db.collection('collection');
if (col) {
col.aggregate([
{$unwind: "$emails"},
{$group: {_id: "$_id",user_emails: { $push: "$emails.email" } } },
{$match: {'user_emails': { $in: ['test#example.com'] } } }
], function(e, r){
if(e){
console.log(error);
}
console.log(r);
db.close();
});
}
It should work, provided you have establish connection and other requirements successfully. Provided your sample documents, it will emit:
[
{
_id: '57017e173915101e0ad5d94a',
user_emails: [
'test#example.com',
'test2#example.com'
]
}
]

Categories