Item.filter is not a function - javascript

Hi everyone I am making a route to get the items that are created by the logged-in user but when I use the .filter function I get an error. Not sure why I am getting this error. I have made other apps before doing the same thing and never got an error
Item.filter is not a function
The my-items route
const requireAuth = require("../middleware/requireAuth");
const express = require("express");
const mongoose = require("mongoose");
const Item = mongoose.model("Item");
router.get("/my-items", requireAuth, async (req, res) => {
try {
const items = Item.filter((item) => item.userId === req.user.userId);
res.send(items);
} catch (err) {
console.log(err);
}
});
Item Schema
const mongoose = require("mongoose");
const itemSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
phone: {
type: mongoose.Schema.Types.String,
ref: "User",
},
email: {
type: mongoose.Schema.Types.String,
ref: "User",
},
seller: {
type: mongoose.Schema.Types.String,
ref: "User",
},
title: {
type: String,
required: true,
},
category: {
type: String,
required: true,
},
detail: {
type: String,
requiredL: true,
},
condition: {
type: String,
required: true,
},
price: {
type: Number,
required: true,
},
});
mongoose.model("Item", itemSchema);

const items = await Item.find(({userId:req.user.userId}).lean();
it should return exact items from db that you want you can use more query if you need.

Item is a model but not the documents in the database, you need to do a query first in order to get the items.
router.get("/my-items", requireAuth, async (req, res) => {
try {
const query = Item.find()
query.exec().then(items => {
const filteredItems = items.filter((item) => item.userId === req.user.userId);
res.send(items);
})
} catch (err) {
console.log(err);
}
});

This error can occur when you are trying to use the array methods on other data structures.
This piece of code returns an error .filter is not a function:
const myList = await getList().filter(item => item.myKey > 10);
Solution:
const data = await getList();
const myList = data.filter(item => item.myKey > 10);

Related

Mongoose Database populate issue

This is the code
app.get("/cart", checkAuthentication, function (req, res) {
Orders.find({ user: req.user._id })
.populate('user')
.populate('order')
.exec((err, orders) => {
console.log(orders);
if (err) {
console.log("ERROR /cart :\n" + err);
res.redirect("/");
} else {
const OrderList = [];
orders.forEach((order) => {
const obj = {
order: order.order,
id: order._id
}
OrderList.push(obj);
});
var sum=0
OrderList.forEach(function(item){
sum += item.order.price
});
req.session.sum = sum;
req.session.orders = OrderList;
res.render("cart", { itemList: OrderList, login: true, name: req.user.name });
// res.render("cart", { itemList: OrderList, login: false, name: "abc" });
}
});
});
This is order model =>
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const orderSchema = new Schema({
user: { type: Schema.Types.ObjectId, ref: "User" },
order: { type: Schema.Types.ObjectId, ref: "SellingItem" },
date: { type: Date, default: Date.now }
});
module.exports = mongoose.model("Orders", orderSchema);
THIS IS THE ERROR
ERROR(null)
This is the github link for my repo - https://github.com/Paras0750/Bakery_Website/
I am trying to populate orders field but it is showing null.
You are importing csv file with _id value. It will become string in the database instead of ObjectId. That's why it cannot populate. Your code is correct.

Express doesn't get another user with .map()

I came to a problem, where I can create conversations with multiple people 2 and so on. However, I can't understand why it doesn't store data to seperate User models.
Here is a code that you only need to know:
router.post(
"/",
auth,
[
check("conversators", "There should be at least two conversators").isLength(
{ min: 2 }
),
],
async (req, res) => {
const { conversators } = req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
let conversation = new Conversation({
user: req.user.id,
conversators: conversators,
});
await conversators.map(async (conversator) => {
let user = await User.findById(conversator);
let newData = user;
newData.conversations.push(conversation.id);
console.log('Created data', newData);
let newUser = await User.findOneAndUpdate(
{ user: conversator },
{
$set: {
newData,
},
},
{ new: true }
);
await newUser.save();
console.log(newUser);
});
await conversation.save();
res.status(200).json(conversation);
} catch (error) {
console.error(error.message);
res.status(500).send("Server error.");
}
}
);
module.exports = router;
What I can assure is that this line: console.log('Created data', newData); prints the desired data. However, the next console: console.log(newUser); prints the same User model as the previous one.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true,
},
surname: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
conversations: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "conversation",
},
],
date: {
type: Date,
default: Date.now,
},
});
module.exports = User = mongoose.model("user", UserSchema);
The reason might be the difference in search methods used to get a record for newData and newUser. You have used User.findById for newData, which will obviously return different objects for different ids. But User.findOneAndUpdate uses filter criteria that may satisfy several results, but only first will be returned. So it boldly depends on what that user field is.
Here is the part that I changed and started to see the data on MongoDB:
await conversators.map(async (conversator) => {
let user = await User.findById(conversator);
let newData = user;
newData.conversations.push(conversation.id);
new Promise(async (resolve, reject) => {
user = await User.findOneAndUpdate(
{ id: conversator },
{
$set: {
newData,
},
},
{ new: true }
);
return resolve;
})
return await user.save();
});
Posted on behalf of the question asker

How do I add new object or push into array Mongodb Compass NodeJS Express (update is not a function)?

At this moment I try to find the query which works in this case, but then want to update the object. So I want to check if review object exist and if not then create that key name first and then push that object into an array. Else push into that in existing object of array.
Default object looks like (without review object):
const mongoose = require('mongoose');
const musicSchema = mongoose.Schema({
id: {
type: Number,
required: true
},
artist: {
type: String,
required: true
},
title: {
type: String,
required: true
},
release_year: {
type: Number,
required: true
},
genre_id: {
type: Number,
required: true
},
image_url: {
type: String,
required: true
},
reviews: [{
id: {
type: Number,
required: true
},
locale: {
type: String,
required: true
},
rating: {
type: Number,
required: true
},
comment: {
type: String,
required: true
}
}]
});
const Music = mongoose.model("Music", musicSchema); // now we have to create our model
console.log;
module.exports = Music; // export our created model
app.post('/addReview/:id', async (req, res) => {
let idNumber = parseInt(req.params.id); // 501437
let reviewObject = req.body; // {id: "501437", locale: "nl", rating: 3, text: "helello"}
try {
const music = client.db('database').collection('music');
const query = { id: idNumber };
const musicSong = await music.findOne(query);
await musicSong.update({ $push: { reviews: reviewObject } }); // error comes from here
} catch (err) {
console.log(err);
}
});
check if reviews field is not exists then initialise it to blank array
push object to reviews
save() to save main document
app.post('/addReview/:id', async (req, res) => {
let idNumber = parseInt(req.params.id); // 501437
let reviewObject = req.body; // {id: "501437", locale: "nl", rating: 3, text: "helello"}
try {
const music = client.db('database').collection('music');
const query = { id: idNumber };
let musicSong = await music.findOne(query);
if (!Array.isArray(musicSong.reviews)) {
musicSong.reviews = [];
}
musicSong.reviews.push(reviewObject);
music.save();
} catch (err) {
console.log(err);
}
});
Second option using updateOne():
It does not require to find, check and save operations if you use update methods,
app.post('/addReview/:id', async (req, res) => {
const query = { id: parseInt(req.params.id) };
let reviewObject = req.body;
try {
const music = client.db('database').collection('music');
await music.updateOne(query, { $push: { reviews: reviewObject } });
} catch (err) {
console.log(err);
}
});

mongoose populate one to many realtion

I'm trying populate function in mongoose docs
i've searched a lot for this, i couldn't find anything.
and i have one more question. is this good approach to do this since i would need books whenever i need author in my front end code
is there any other ideas to get this behavior?
I've a simple example.
here is my models
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Author = new Schema({
name: {
type: String,
required: true,
},
books: [{ type: Schema.Types.ObjectId, ref: "Book" }],
});
const Book = new Schema({
title: {
type: String,
required: true,
},
author: { type: Schema.Types.ObjectId, ref: "Author" },
});
module.exports = {
Author: mongoose.model("author", Author),
Book: mongoose.model("book", Book),
};
then I created some routes
const express = require("express");
const { Book, Author } = require("../models");
const router = express.Router();
router.get("/books", async (req, res) => {
let books = await Book.find();
res.send(books);
});
router.get("/authors", async (req, res) => {
let authors = await Author.find();
res.send(authors);
});
router.post("/book/:author", async (req, res) => {
let { title } = req.body;
let { author } = req.params;
let book = new Book({
title,
author,
});
book.save().then((data) => {
res.send(data);
});
});
router.post("/author", (req, res) => {
let { name } = req.body;
let author = new Author({
name,
});
author.save().then((data) => {
res.send(data);
});
});
module.exports = router;
then I created a new Author and new Book calling these 2 end points I created using postman
here is result from GET /authors
[
{
"books": [],
"_id": "6085a6fb098c0003944b1dcd",
"name": "john",
"__v": 0
}
]
why books are empty array?
I was expecting it to be something like this
[
{
"books": [
{
"_id": "6085a702098c0003944b1dce",
"title": "hello",
}
],
"_id": "6085a6fb098c0003944b1dcd",
"name": "joe",
"__v": 0
}
]
if your other routes have no problems when saving and retrieving data (check the result using mongo shell or Mongo compass or anything else, or better, write tests to automate things for you before coding, anyhow), you should populate books field
router.get("/authors", async (req, res) => {
let authors = await Author.find().populate('books').lean();
res.send(authors);
});
this is your code with out considering your http handler
try it with and without populate to understand the difference
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/testX', { useNewUrlParser: true, useUnifiedTopology: true });
const Author = mongoose.model('Author', {
name: {
type: String,
required: true,
},
books: [{ type: mongoose.ObjectId, ref: 'Book' }],
});
const Book = mongoose.model('Book', {
title: {
type: String,
required: true,
},
author: { type: mongoose.ObjectId, ref: 'Author' },
});
(async () => {
try {
const book1 = new Book({ title: 'titleHere' });
await book1.save();
const author1 = new Author({ name: 'nameHere' });
author1.books.push(book1);
await author1.save();
const authors = await Author.find().populate('books').lean();
console.log(authors);
} catch (error) {
console.error(error);
}
})();

Mongoose assign a collection to another

I am trying to add a post to a user collection after the user was created with empty posts. I have tried with populate with no success .. any help is much appreciated.
// Post Model
const mongoose = require('mongoose');
const { Schema } = mongoose;
const UserModel = require('./user-model');
let PostSchema = new Schema({
author: {
ref: 'users',
type: Schema.Types.ObjectId
},
content: String,
description: String,
date: {
default: new Date(),
type: Date
},
title: String,
updatedAt: {
default: new Date(),
type: Date
}
});
let PostModel = mongoose.model('posts', PostSchema);
module.exports = PostModel;
// User Model
const mongoose = require('mongoose');
const { Schema } = mongoose;
const PostModel = require('./post-model');
let UserSchema = new Schema({
name: {
type: String
},
email: {
lowercase: true,
type: String,
trim: true,
unique: true
},
password: {
type: String,
},
postList: [{
ref: 'posts',
type: Schema.Types.ObjectId
}],
});
const UserModel = mongoose.model('users', UserSchema);
module.exports = UserModel;
// save post controller
exports.savePost = (request, response, next) => {
let { author, description, title } = request.body;
let post = new PostModel({ author, description, title }).save();
UserModel.findById(author)
.then((user) => {
user.postList.push(post);
// Still Fails
// How can i assign the post to the user ?
});
}
Is there any way of doing this other then push or populate ?
To solve this problem I prefer to use $push of mongo
UserModel.findOneAndUpdate({
_id: author.id,
{
$push: {
postList: post
}
}
});
You need to follow this process to save successfully
Save post if success then
Update user to push postId in postlist
can try this one
exports.savePost = (request, response, next) => {
let post = new PostModel(request.body)
post.save(function(err, data) {
if(err) {
//return error
}
// check by console your author is present or not
// let author in your req.body
let author = req.body.author
UserModel.findOneAndUpdate({_id: author},{$push: {postList: post._id}},{new:true} function(error, user) {
if(error) {
// return error
}
console.log(user)
// return success
})
});
}
exports.savePost = (request, response, next) => {
let { user, description, title } = request.body;
let post = new PostModel({ user, description, title });
post.save()
.catch((error) => {
if (error)
throw new Error(error);
})
.then((post) => {
UserModel.findOneAndUpdate({ _id: user }, {$push: { postList: post._id } })
.populate('postList')
.catch((error) => {
if (error)
throw new Error(error);
})
.then((user) => {
user.postList.forEach((item, postion) => {
console.log(`${item} -at ${postion} \n`);
});
});
});
}
This is what i did and it worked after all. I don't know if this is the correct solution but this is working.

Categories