Mongoose .stream doesn't have populated fields - javascript

I have a schema "Reports" that looks like this:
var Reports = new Schema(
{
identifiersub: { // Id of reported submission, populate stuff
type: Schema.Types.ObjectId,
ref: "Submission"
},
identifiercom: { // Id of reported comment, populate stuff
type: Schema.Types.ObjectId,
ref: "Comments"
},
identifieruse: { // Id of reported user, populate stuff
type: Schema.Types.ObjectId,
ref: "AccountDetails"
},
solved: { // Whether this problem has been solved or not
type: Boolean,
default: false
},
processed: [{ // Array of moderators who were participating in processing this report
type: Schema.Types.ObjectId,
ref: "AccountDetails"
}],
type: String, // Type of content. bug, user, submission or comment
reports: [ // Additional text for each type of reported content
{
description: String, // Text from select component. For bugs: the feature that is affected,
reason: String, // Reason for this report
by: { // Reporter
type: Schema.Types.ObjectId,
ref: "AccountDetails"
}
}
],
notes: [{ // Admin notes
title: String, // Fleshed out discussion/reasoning
note: String, // Decided outcome that each note represents
outcome: String, // ("Keep reported", "delete", etc)
date: Date, // Date this note was added
moderator: { // Moderator who added this note
type: Schema.Types.ObjectId,
ref: "AccountDetails"
}
}]
},
{ strict: false, timestamps: true }
)
And in my admin panel I want to implement a search function that searches all reports with the specified keyword. The most important field here is reports: it's an array of objects containing a "by" field which is an ObjectId. Now I wanted to populate the username for this id, but I'm not seeing it in my document...I use the .stream method to check the whole document including nested objects and arrays of objects. Here's my query:
var cursor = Reports
.find({ type: req.query.type})
.limit(500)
.populate("notes.moderator reports.by processed", "username")
.populate("identifieruse", "username dob email ipaddress")
.populate("identifiercom", "by.username comment")
.populate("identifiersub", "meta.title by deleted")
.sort("-createdAt")
.lean()
.stream();
cursor.on('data', function(doc) {
console.log(doc);
if (doc.toString().includes(key)) results.push(doc)
})
cursor.on('error', function(err) {
return catcherror(new Error(err), res)
})
cursor.on('close', function() {
console.log(results);
return res.send(results)
})
Thanks for help!

Use .cursor() instead of .stream() and it works.

Related

How do I push to an array within an array in a collection with mongoose?

I have a User schema created with Mongoose that holds a customer array, and inside that customer array there is another fleet array. I have figured out how to push to the customer array within the User schema, however I can not figure out how to loop through the customers, find the customer via id or name, and then push data into the fleet array.
Here is my User schema:
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
username: {
type: String,
default: ''
},
password: {
type: String,
default: '',
},
registerDate: {
type: Date,
default: Date.now()
},
customer: [{
name: {
type: String,
default: '',
},
email: {
type: String,
default: 'No email addresses found',
},
fleet: [{
unitType: {
type: String,
default: 'No type selected',
},
unitNumber: {
type: String,
default: 'No unit number provided',
},
vinNumber: {
type: String,
default: 'No vin number provided'
},
}]
}]
});
module.exports = mongoose.model('User', UserSchema);
I was able to figure out how to push a new customer into the customer array no problem. My problem is I do not get how I can loop through the customer array, and once I find the customer that I need, push data into the fleet array. I am really just stumped on how to word my Google search! Hopefully this is detailed enough, and please let me know if you need to see any other code.
You need to use positional '$' operation. Read here
UserSchema.update(
{'customer.email':'xyz#email.com'},
{
$push:{
'customer.$.fleet':<fleet object>
}
},function(err,result){
})
--- OR ---
UserSchema.update(
{'customer.email':'xyz#email.com'},
{
$set:{
'customer.$.fleet':[fleet array]
}
},function(err,result){
})
Hope this helps.

How to push element parent in Mongoose?

I want to push an nested element Mongoose.
Check the schema:
const Messages = new mongoose.Schema({
/*[user]*/
author: {
type: Schema.Types.ObjectId,
ref: 'Users'
},
/*[room]*/
room: {
type: Schema.Types.ObjectId,
ref: 'Rooms'
},
message_body: String,
message_status:{type: Boolean, default: false},
created_at: { type: Date, default: Date.now }
});
I want to create a Message with room and Author insert, how to use that?
Imagine you have an 'author' object and a 'room' object. These are going to be the parents. Your message object would be like this:
var newMessage = new Message({author: authore._id, room: room._id, message_body: messageBody ....});
newMessage.save()
.then(() => {
/*** do more things **/
});
Then you will be able to use 'populate' option to make Mongoose refilling author and room fields with the whole objects.

Mongoose/MongoDb ,how to validate an array of Ids against another model

I have 2 moongose Schema:
var Schema2 = new Schema({
creator : { type: String, ref: 'User'},
schema_name : [{ type: String}],
});
var Schema1 = new Schema({
creator : { type: String, ref: 'User'},
schema_ref : [{ type: String, ref: 'Schema2' }],
});
Would like to know which is the best practice when I create a new Schema1 check that every element of array schema_ref, have the same creator.
Because schema1 elements are added by client form and so i have to check that the schema_ref elements are owned by same User that send the form
You can try with either validator function, or with a simple 'save' middleware:
Schema1.pre('save', function(next) {
let owner;
for (let entry in this.schema_ref) {
if (!owner) {
owner = entry;
} else {
if (entry !== owner) {
return next(new Error("owner mismatch");
}
}
}
});
Also, your schema might not work as you expect it to, it looks like you actually need:
schema_ref: [{
type: {type: String},
ref: "User"
}]
Additionally, take a look at id-validator plugin, or some similar to that - it will, in addition to your validation, also check that all ref-type properties like this actually exist in the other (Users) collection.

MongoDB w/ Mongoose - Where to put syntax to ensureIndex spanning multiple fields?

I'm trying to implement this solution and I'm not sure where to put it. I see the db variable called frequently, but I'm still new to node and mongoDb, so I don't know how to call it in my Model. Here is the syntax to ensure an index spanning multiple fields...
db.collection.ensureIndex( {
description: "text",
title: "text"
} );
Here is my model...
// Module dependencies.
var mongoose = require('mongoose'),
config = require('../../config/config'),
Schema = mongoose.Schema,
findOrCreate = require('mongoose-findorcreate'),
textSearch = require('mongoose-text-search');
// Product Schema
var ProductSchema = new Schema({
created: {
type: Date,
default: Date.now
},
retailer: {
type: String,
required: true,
trim: true
},
retailer_category: {
type: String,
required: true,
trim: true
},
product_id: {
type: String,
required: true,
trim: true
},
link: {
type: String,
trim: true
},
title: {
type: String,
trim: true
},
price: {
type: Number
},
// Rating - 0 out of 5 (can be decimal)
rating: {
type: Number
},
description: {
type: String,
trim: true
},
variations: {
type: Schema.Types.Mixed,
default: []
},
images: {
type: Boolean,
default: false
}
});
// Validations
ProductSchema.index({ retailer: 1, product_id: 1 }, { unique: true });
// Statics
ProductSchema.statics = {
load: function(id, cb) {
this.findOne({
_id: id
}).exec(cb);
}
};
// Plug-Ins
ProductSchema.plugin(findOrCreate);
ProductSchema.plugin(textSearch);
mongoose.model('Product', ProductSchema);
var Product = mongoose.model('Product', ProductSchema);
Product.ensureIndexes( function(err) {
if (err) {
console.log(err);
}
})
It's worth noting:
When your application starts up, Mongoose automatically calls ensureIndex for each defined index in your schema. While nice for development, it is recommended this behavior be disabled in production since index creation can cause a significant performance impact. Disable the behavior by setting the autoIndex option of your schema to false.
from http://mongoosejs.com/docs/guide.html
I scratched my head over this one too. After digging around the mongoose test cases, I found that ensureIndex resides in a mongoose model's collection property.
var ProductModel = mongoose.model('Product', ProductSchema);
ProductModel.collection.ensureIndex({
description : 'text',
title : 'text'
}, function(error, res) {
if(error){
return console.error('failed ensureIndex with error', error);
}
console.log('ensureIndex succeeded with response', res);
});
Note that a callback is required, or Mongo will throw the error:
Error: Cannot use a writeConcern without a provided callback

Inserting Object ID's into array in existing Mongoose schema with Node.js

I have an existing News articles section that I want to add categories to for more refined searching, my Schema's are as follows:
var ArticleSchema = new Schema({
title: String,
body: String,
author: {
type: Schema.Type.ObjectId,
ref: 'User',
required: true
},
image: String,
catagories: [{
type: Schema.Types.ObjectId, ref: 'Catagory'
}],
meta: {
created: {
type: Date,
'default': Date.now,
set: function(val) {
return undefined;
}
},
updated: {
type: Date,
'default': Date.now
}
}
});
ArticleSchema.statics.search = function (str, callback) {
var regexp = new RegExp(str, 'i');
return this.find({'$or': [{title: regexp}, {body: regexp}]}, callback);
};
module.exports = ArticleSchema;
var CatagorySchema = new mongoose.Schema({
name: { type: String, unique: true },
});
module.exports = CatagorySchema;
I want a user friendly input for selecting categories (don't even know what is best here, be it check-box's or a simple comma separated text input etc.). My question is what is the best practice for obtaining this kind of input and translating that into the Article Schema (providing the categories exist). If anyone could point me in the right direction it would be much appreciated. Thanks.
Keep the category names you want to search for in an array
{
categories: ["cat1", "cat2"]
}
then you can add an index to it and do a $in query. the current schema is not very good because you cannot look for the category in a single query but need to resolve all the "categories" links first.

Categories

Resources