Aggregate is not a function - Mongoose Nodejs - javascript

Can somebody help me to fix this, here is my code for aggregate from mongoose:
export class GetVehiclesbyKotaCommandHandler {
constructor(namaKota) {
return new Promise((resolve, reject) => {
VehiclesDB.find().populate({
path: 'mitraId',
model: 'RentalDB',
select: 'namaKota'
}).aggregate([
{
$match : {
namaKota:namaKota
}
}
]).lean().then((dataVehicles)=>{
if(dataVehicles !== null){
resolve(dataVehicles);
} else {
reject (new NotFoundException('Couldn\'t find any Vehicles with namaKota' + namaKota));
}
}).catch((errDataVehicles)=>{
reject(new CanNotGetVehiclesException(errDataVehicles.message));
});
});
}}
And I get an error like this on the console:
TypeError: _VehiclesDB2.default.find(...).populate(...).aggregate is not a function
DONE, I Thanks for Hana :)
And i change my mitraId type ObjectId
mitraId : {
type: Schema.Types.ObjectId,
required: true
},

Try to avoid find, populate, lean function here and follow as like below
export class GetVehiclesbyKotaCommandHandler {
constructor(namaKota) {
return new Promise((resolve, reject) => {
VehiclesDB.aggregate([
{
$lookup: {
from: 'RentalDB',
localField: 'mitraId',
foreignField: '_id',
as: 'mitra'
}
}, {
$unwind: "$mitra"
}, {
$match: {
"mitra.namaKota": namaKota
}
}
]).then((dataVehicles)=>{
if(dataVehicles !== null){
resolve(dataVehicles);
} else {
reject (new NotFoundException('Couldn\'t find any Vehicles with namaKota' + namaKota));
}
}).catch((errDataVehicles)=>{
reject(new CanNotGetVehiclesException(errDataVehicles.message));
});
});
}}

You can use $lookup in the aggregation statement instead of using find, and populate here.
Like this:
VehiclesDB.aggregate([
{
$lookup: {
from: 'RentalDB',
localField: 'mitraId',
foreignField: '_id',
as: 'mitra'
}
}, {
$unwind: "$mitra"
}, {
$match: {
"mitra.namaKota": namaKota
}
}
])
I hope this helps.

Related

Mongoose Pre /^findOneAnd/ Hook Middleware Doesn't Fire

I have CommenentSchema:
const CommentSchema: Schema = new Schema(
{
article: {
type: Schema.Types.ObjectId,
ref: "Article",
},
comment: {
type: String,
required: [true, "Cannot post an empty comment"],
},
commentBy: {
type: Schema.Types.ObjectId,
ref: "User",
},
},
{
toJSON: {
virtuals: true,
transform: (_doc, ret) => {
delete ret.id;
delete ret.__v;
},
},
toObject: { virtuals: true },
timestamps: true,
}
I'm trying to get the totalComments of an article (in a separate ArticleSchema) which I was able to achieve with aggregate and pre save middleware like so:
// Comment Count
// 1 - Calc. number of comments of an article when a comment is submitted
CommentSchema.statics.calcTotalComments = async function (articleId) {
const stats = await this.aggregate([
{
$match: { article: articleId },
},
{
$group: {
_id: "article",
nComment: { $sum: 1 },
},
},
]);
if (stats.length > 0) {
// update article
await Article.findByIdAndUpdate(articleId, {
totalComments: stats[0].nComment,
});
} else {
// set to default
await Article.findByIdAndUpdate(articleId, {
totalComments: 0,
});
}
};
CommentSchema.post("save", function () {
// points to current comment
this.constructor.calcTotalComments(this.article);
});
I also want the number of totalComments to change when a comment is deleted but it doesn't fire at pre /^findOneAnd/
// 2 - Calc. number of comments of an article when a comment is updated/deleted
CommentSchema.pre<Query<ICommentDocument, ICommentDocument>>(
/^findOneAndUpdate/,
async function (next: Function) {
// points to query of coment
// #ts-ignore: igore property doc does not exist on type Query...
this.doc = await this.model.findOne(this.getFilter());
// #ts-ignore: igore property doc does not exist on type Query...
console.log(this.doc);
next();
}
);
CommentSchema.post<Query<ICommentDocument, ICommentDocument>>(
/^findOneAnd/,
async function () {
// #ts-ignore: igore property doc does not exist on type Query...
await this.doc.constructor.calcTotalComments(this.doc.article);
}
);
I have tried all previous solution but none did work. Even the pre hook doesn't fire a simple console.log('hello');
What am I doing wrong?

Is there any way to compare an array in mongo aggregate?

This code does not match the bu.subUser with subUser and due to mismatch nothing is returned. How to achieve the output?
{
$match: {
subUser: {
$ne: blockedUsers.map((bu) => {
return bu.subUser;
}),
},
},
}
{ $match: { subUser: { $nin: blockedUsers.map((bu) => bu.subUser) } } }

Mongodb - Update property per object in array of object, Insert if doesn't exists

I wish to update a property per object in array of objects, but if some of the objects doesn't exists, insert the object instead.
Currently I used "upsert", which creates a new document when no document matches the query, unfortunately it is replacing a single item with my entire list.
Worth to mention that I am using mongoist to perform an async requests.
My code:
this.tokenArray = [
{ token: "654364543" },
{ token: "765478656" },
{ token: "876584432" },
{ token: "125452346" },
{ token: "874698557" },
{ token: "654364543" }
]
database.upsertDatebaseItem(this.tokenArray.map(x => { return x.token }), { valid : true }, 'Tokens');
async upsertDatebaseItem(itemKey, itemValue, collectionName) {
try {
await this.database[collectionName].update({ token : { $in: itemKey}}, { $set: itemValue }, {upsert : true} , {multi : true});
} catch (error) {
console.log(`An error occurred while attempting to update ${itemType} to the database: ${error}`);
return false;
}
}
Found the way to do it:
const bulkUpdate = this.tokenArray.map((x) => {
return {
"updateOne": {
"filter": { "token": x.token },
"update": { "$set": { "valid": true } },
"upsert": true
}
};
});
and:
this.database[collectionName].bulkWrite(bulkUpdate);
To upsert with mongoist, use the following:
var bulk = db.collection.initializeOrderedBulkOp()
for(var doc of docs) bulk.find( { _id: doc._id } ).upsert().updateOne(doc); // or use replaceOne()
await bulk.execute();
Converted to your case that would be
var bulk = db.collectionName.initializeOrderedBulkOp()
for(var tokenItem of tokenArray) bulk.find( { token : tokenItem.token } ).upsert().updateOne(tokenItem); // or use replaceOne()
await bulk.execute();

Is MongoDB conditional aggregation available in Meteor 1.4.x ?

I'm trying to publish certain fields to a page based on a parameter of a document in a mongo collection. This is from the MongoDB manual: https://docs.mongodb.com/manual/reference/operator/aggregation/cond/
Does Meteor support conditional aggregation?
return Cases.find({
subscribers: { $in: [this.userId] }
}, {
fields: { $cond: [ { $eq: ['classified', true] } , Cases.privateFields, Cases.publicFields ] }
});
So, I realized I was approaching aggregates incorrectly. After doing some research on options to implement aggregation (meteorhacks) I decided to implement my own, which keeps the reactivity of the collection:
Extend Mongo.Collection
class CasesCollection extends Mongo.Collection {
conditionalFields(selector, modifier) {
let cond = modifier.fields[0],
pos = modifier.fields[1],
neg = modifier.fields[2];
if ( cond ) {
modifier = { fields: pos };
} else {
modifier = { fields: neg };
}
const cursor = this.find(selector, modifier);
return cursor;
}
}
Usage:
Meteor.publish('cases.dashboard', function casesDashboard() {
if (!this.userId) {
return this.ready();
}
return Cases.conditionalFields({
subscribers: { $in: [this.userId] }
}, {
fields: [ { $eq: ['classified', true] } , Cases.privateDashboardFields, Cases.dashboardFields ]
});
});

Node.js: How do I $pull from an array of $oid in Mongo/Mongoose?

I'm trying to remove an object from an array of $oid from within a single document with mongoose using update.
Here is a hypothetical schema based on the schema I'm using now:
var TestSchema = Schema({
name: { type: String },
otherRefs: [ {type: Schema.ObjectId, ref: 'OtherSchema' } ]
});
An example document would look like (note: these aren't actual ObjectIDs from my db - I just randomly typed them in to give an idea of what the document would look like - the documents in my actual db have valid $oid values:
{ "_id" : { "$oid" : "56da0b6326008d0c24a4f029" },
"name" : "name1",
"otherRefs" : [
{"$oid" : "56c340259402505c2720541b"},
{"$oid" : "56c340259402505c2720541e"},
{"$oid" : "56c340259402505c2720541f"},
{"$oid" : "56d758862494c411001ca603"}
]
}
Here is the query I'm trying to use:
TestSchema.update(
{ '_id': testResult._id },
{ $pull: { 'otherRefs': { $oid : mongoose.Schema.ObjectId( refResult._id ) } } },
false,
true,
function(err, success) {
if (err) {
res.json(err);
} else {
res.json('success', success);
}
}
)
Have also tried { $pull: { 'otherRefs': refResult._id } } with no success.
testResult._id and refResult._id are received from previous queries.
Been at this for a while now and can't seem to wrap my head around this problem. Hoping someone can help me figure out what I'm doing wrong.
Thanks!
EDIT:
Now using:
TestSchema.update(
{ '_id': testResult._id },
{ $pull: { 'otherRefs': refResult._id ) } },
function(err, success) {
if (err) {
console.log(err);
} else {
console.log('Success');
}
}
)
The query doesn't hang anymore and "Success" is getting logged but nothing is changed in the actual document in DB.

Categories