toArray is not a function in mongodb,mongoose - node.js

to Array is not a function in mongo database, mongoose, node.js
`getCartProducts: (userId) => {
return new Promise(async (resolve, reject) => {
let cart Items = await db.cart.aggregate([
{`your text`
$match: { user: user Id }//matched with the id
},
{
$lookup: {
from: "db.products",
let: { proList: '$products' },
pipeline: [
{
$match: {
$expr: {
$in: ["$_id", '$$proList']
}
}
}
],
as: 'cart Items' //converted as cart Items name
}
}
]).`to array`()
resolve(`cart Items`)
})
}
db. cart. aggregate().to Array is not a function
I tried to remove the to array but it shows as un defined

Issue is you're doing toArray() on promise,
it should be something like this.. you don't need to create custom promise..
const getCartItems = () => {
// ...
const items = await db.cart.aggregate([...])
return items.toArray();
...
}

Related

Is there a solution when mongodb query parameter null or exists?

I'm trying to make get customer & store from mongodb use mongoose Model,
getCustomer Function parameter are customer and store, But sometimes store parameter is null || undefined
// Mongoose Model
const Customer = require("../models")
// Find customer && Store
const getCustomer = async (customer, store) => {
const result = await Customer.aggregate([
{
$match: {
customerId: customer.id,
storeId: store.id,
},
},
]);
return result;
};
So this $match query in aggregate is return Error, Because store.id is not found.
Can you tell me what query I should use if store data is passed unconditionally?
Pass the store.id conditionally, like this:
const getCustomer = async (customer, store) => {
const result = await Customer.aggregate([
{
$match: {
customerId: customer.id,
...(store && store.id ? { storeId: store.id } : {})
},
},
]);
return result;
};

mongodb changestream “pipeline” not working nodejs

I have the following change stream but it does not function changed is not logged once I update using mongo compass.
var pipeline = [
{ $match: { _id: ObjectId(id) } }
];
try {
const collection = client.db("mydb").collection("shop");
const changeStream = collection.watch(pipeline);
changeStream.on('change', (next) => {
//console.log(next);
console.log('changed')
}, err => {
console.log(err);
});
} catch (err) {
console.log(err)
}
Is the problem that you don't normally update the _id of a document in a collection? If, for some reason, you are updating the _id then maybe the problem is in how you're referencing your $match. This works for me:
const pipeline01 = [
{ $match: { 'updateDescription.updatedFields.fieldIamInterestedIn': { $ne: undefined } } },
{ $project: { 'fullDocument._id': 1, 'fullDocument.anotherFieldIamInterestedIn': 1 } },
];
theCollectionIamWatching.watch(pipeline01, { fullDocument: 'updateLookup' }).on('change', async (data) => {
// do the thing I want to do using data.fullDocument
});

How to add object to a nested array in mongoDB and nodeJS

I have no clue how can I push an object to a nested array
this is the Board document:
{
"boardMembers": [
"5f636a5c0d6fa84be48cc19d"
],
"boardLists": [
{
"cards": [],
"_id": "5f6387e077beba2e3c15d15a",
"title": "list one",
"__v": 0
}
],
"_id": "5f63877177beba2e3c15d159",
"boardName": "board1",
"boardPassword": "123456",
"boardCreator": "5f636a5c0d6fa84be48cc19d",
"g_createdAt": "2020-09-17T15:57:37.616Z",
"__v": 2
}
I need to push a task inside the cards array (to a specific list with ID)
here is the code:
outer.post("/add-task/:id", auth, boardAuth, async (req, res) => {
const listId = req.params.id;
const board = await Board.findOne({ _id: req.board._id });
if (!board) return res.status(404).send("no such board");
const list = await List.findOne({ _id: listId });
if (!list) return res.status(404).send("List not found");
const task = new Task({
text: req.body.text,
});
board.boardLists.map((list) => {
if (listId.toString() === list._id.toString()) {
list.cards.push(task);
} else {
console.log("no task");
}
});
await board.save();
res.send(board);
});
now the problem is when I make the request in postman its shows me the task inside the cards array i want but its not saving it to the mongoDB
You're using array.map() but:
Nothing is returned in the callback of map(), which will return an array with each element undefined;
You aren't assigning the array returned by map() to anything.
So, you can use array.map() to return an array in which the task is pushed to the desired list in board.boardLists like so:
board.boardLists = board.boardLists.map((list) => {
if (listId.toString() === list._id.toString()) {
return {
...list,
cards: list.cards.concat(task)
}
} else {
return list
}
});

When I make db process inside async map function, I can't avoid duplicate

I want to add pallet barcode to palletBarcodes field of record.But there is check for avoid add same palletBarcode.I am using below function. But check is not working inside async map function.
myService.js
const palletBarcodes = ["TP2","TP2"]
await Promise.all(palletBarcodes.map(async (palletBarcode) => {
const promise = await this.addPalletBarcode({ transferId, barcode: palletBarcode });
return promise;
}));
async addPalletBarcode({ transferId, barcode, pickerId }) {
const { TransferDataAccess } = this;
const transfer = await TransferDataAccess.getTransfer({ transferId });
if (!transfer) {
throw new TransferNotFoundError();
}
if (transfer.palletBarcodes.length && transfer.palletBarcodes.includes(barcode)) {
throw new PalletBarcodeAlreadyExistsError({ barcode });
}
return TransferDataAccess.pushPalletBarcode({ transferId, barcode });
}
transferDataAccess:
async pushPalletBarcode({ transferId, barcode }) {
const { TransferModel } = this;
return TransferModel
.findOneAndUpdate({
_id: transferId,
},
{
$push: {
palletBarcodes: barcode,
},
})
.lean()
.exec();
}
Instead of $push use $addToSet. $addToSet will treat your key in document as a set and that will automatically avoid duplicates.
You query would then become -
TransferModel.findOneAndUpdate(
{ _id: transferId },
{ $addToSet: { palletBarcodes: barcode } }
);

Paginated results in mongoose with filters on reference document

I have a user and post document as follow:
user: {
"name": "Test",
interests: [
"Sports",
"Movies",
"Running"
]
}
post: {
"title": "testing",
"author": ObjectId(32432141234321411) // random hash
}
I want to query posts and fetch all those posts with author have "sports", "Running" as interests and this will be a paginated query.
How can I do so in mongoose and if not what alternative shall I use ?
Pagination using limit and skip
var limit = 5;
var page = 0; // 1,2,3,4
return Model.find({
/* Some query */
})
.limit(limit)
.skip(limit * page)
.exec().then((data) => {
console.log(data);
});
Try this
const findUser = (interests) => {
return User.find({
interests: {
$in: interests
}
}).exec();
};
const findPost = (query, page = 0) => {
const limit = 5;
return Model.find(query)
.limit(limit)
.skip(limit * page)
.exec();
};
var execute = async () => {
const users = await findUser(["Sports", "Movies", ]);
users.forEach(user => {
user.post = await findPost({
"post.author": user._id
});
});
return users;
}
I used following approach though giving answer with async/await approach but I actually used it using promises.
const fetchPosts = async (req, res) => {
//First find users having those interests.
const users = await User.find({
interests: {
"$in": ["Sports", "Movies"]
}
})
.select('_id')
.exec();
// map over array of objects to get array of ids
const userIds = users.map(u => u._id);
// Then run an in filter on Post collection against author and
//userIds
const posts = await Post.find({
author: {
"$in": [userIds]
}
})
.limit(15)
.skip(0)
.exec();
}

Resources