skip to Main Content

I am trying to form a search query with mongoose.find() but I keep getting an error back and I am not sure why. It receives a query parameter and return the items whose name OR description contain the parameter.

Here is the code for the search function:

const searchQuery = async (q) => {
  try {
    const menuItems = await MenuItems.find({
      $or: [
        { name: { $regex: q, $options: "i" } },
        { description: { $regex: q, $options: "i" } }
      ]
    });

    return menuItems;
  } catch (error) {
    return error;
  }
};

Here is how information is being passed:

const searchQuery = async (req, res) => {
  try {
    const menu = await MenuItems.searchQuery(req.query.q);
    res.send(menu);
  } catch (error) {
    res.status(500).send(error);
  }
};

I am testing/calling it by the route "/api/menu/search?q=pizza" as a get request in postman and I keep getting this error:

{
    "stringValue": ""search"",
    "valueType": "string",
    "kind": "ObjectId",
    "value": "search",
    "path": "_id",
    "reason": {},
    "name": "CastError",
    "message": "Cast to ObjectId failed for value "search" (type string) at path "_id" for model "MenuItems""
}

code for menuItems:


const menuItemsSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    unique: true
  },
  price: {
    type: Number,
    required: true
  },
  description: {
    type: String,
    required: true
  },
  imageUrl: {
    type: String
  },
  updatedAt: {
    type: Date,
    default: Date.now
  }
});
menuItemsSchema.set("toJSON", {
  virtuals: true
});
// menu model
const MenuItems = mongoose.model("MenuItems", menuItemsSchema);

2

Answers


  1. Since the comment fixed the issue, I added it as the answer.

    Seems the router interprets the path /search as value, You probably have another route something like /api/menu/:id where the router takes /search as the value of :id.

    You have to change the order since the routes are being resolved in top-to-bottom order.

    Add the /api/menu/search router before /api/menu/:id.

    Login or Signup to reply.
  2. The error you are encountering is due to the fact that Mongoose is trying to cast the q parameter as an ObjectId because it’s being treated as if you are trying to find a document by its _id field. To resolve this issue, you should make sure that q is properly passed as a query parameter and that your searchQuery function is correctly handling it.

    Here’s the corrected code for your searchQuery function:

    const searchQuery = async (q) => {
      try {
        const menuItems = await MenuItems.find({
          $or: [
            { name: { $regex: q, $options: "i" } },
            { description: { $regex: q, $options: "i" } }
          ]
        });
    
        return menuItems;
      } catch (error) {
        return error;
      }
    };
    

    The issue here seems to be in how you are calling the searchQuery function in your route handler. You should pass the req.query.q parameter to the function, not try to access it as a property of the MenuItems model. Here’s the corrected route handler:

    const searchMenu = async (req, res) => {
      try {
        const menu = await searchQuery(req.query.q);
        res.send(menu);
      } catch (error) {
        res.status(500).send(error);
      }
    };
    

    Make sure that your route is also defined correctly:

    app.get("/api/menu/search", searchMenu);
    

    With these changes, your route handler will correctly call the searchQuery function with the q query parameter, and the error should be resolved. Now, you should be able to call the route "/api/menu/search?q=pizza" without encountering the ObjectId casting error.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search