4

I'm trying to do a simple mongoose query using the query string. This works

router.get('/', function(req,res) {
    myModel.find({name:"test e"}, function(err,data){
        if(err) console.log(err)
        res.json(data);
    });

});

This doesn't work (I get the whole collection)..

router.get('/', function(req,res) {
    console.log(req.query.q)
    myModel.find(req.query.q, function(err,data){
        if(err) console.log(err)
        res.json(data);
    });

});

with this request

/api/myModel?q={name:"test e"}

I don't think it's an url encoding issue since I print the 'q' var and it looks fine server side.

Side question: if this isn't the standard mode, what's the RESTful standard way to query a db?

Edit for more general details: I don't need a simple access by id or name like Ashley B suggests, I need a proper search engine for my db (the user, using a graphic web interface, have to be able to query each field separately, potentially)

Edit 2: thanks to Blakes Seven I solved my initial problem, but if you know or use a better way to perform a complex query I would happy to discuss. Maybe I should expose anther resource "/api/seach"?

alfredopacino
  • 2,979
  • 9
  • 42
  • 68
  • Sorry I will skip answering mongoose related part as I have not used that db. however there is now a standard that you can following when dealing with json based resources which is [jsonapi specification](http://jsonapi.org/) – Dmitry Matveev Feb 21 '16 at 22:29
  • Well your title says it all. It's a "string". The query is not supposed to be a "string" but an "object". So `JSON.parse(req.query.q)` to make it anobject. But it's probably not really that great an idea to allow that directly from an URL. Also there is a typo in your question where the issued query should be `{ "name": "test e"}` with a colon `:` and not an equals `=` – Blakes Seven Feb 21 '16 at 22:38
  • yeah I forgot the quotes on "name", that's all, thanks. – alfredopacino Feb 21 '16 at 23:01

3 Answers3

3

I think I can answer your first question by answering your second (side question).

Let's say you have a User model, normally you'd have an endpoint to get all users, like so:

router.get('/users', function(req, res) {
    // find all users
    users.find({}, function(err, data){
        if(err) console.log(err)
        res.json(data);
    });
});

To find a specific user you then have an endpoint like so:

router.get('/users/:name', function(req, res) {
    // get the user's name from the url and find that user
    users.find({name: req.params.name}, function(err, data){
        if(err) console.log(err)
        res.json(data);
    });
});

So rather than passing the whole query through the query string, you just find use a specific part. Allowing the users to directly access your data with their own queries makes it much much harder to secure.

Ash
  • 6,483
  • 7
  • 29
  • 37
3

I would recommend you to use some library to parse the querystrings to mongoDB queries. It would fix your problem and make your code better.

querymen would help you by transforming /myModel?q=test+e into {name: 'test e'}, giving you full control over the querystring schema.

var querymen = require('querymen')

// querymen.middleware() defines an express middleware with querystring schema
router.get('/', querymen.middleware({
  q: {
    type: String,
    paths: ['name']
  }
}), function(req, res) {
  console.log(req.querymen.query) // {name: 'test e'}
  myModel.find(req.querymen.query, function(err,data){
    if(err) console.log(err)
    res.json(data);
  });
});
Sonicd300
  • 1,950
  • 1
  • 16
  • 22
Diego Haz
  • 952
  • 1
  • 6
  • 24
0

The proper query should look like this:

/api/myModels?name=test%20e

The myModals part is in plural.

Check here: How to design RESTful search/filtering?

Community
  • 1
  • 1
Patryk Wojtasik
  • 421
  • 4
  • 14
  • Since the query could counts ~30 values in my case I would prefer a single querystring param for the whole json query and other params for pagination, limits, offset, order. What do you think? – alfredopacino Feb 21 '16 at 22:39
  • In this case you can use something like jQuery.param(), [qs library](https://github.com/ljharb/qs) or write your own function to achieve it. – Patryk Wojtasik Feb 21 '16 at 22:49