2

The query on the API is structured like this:

../myapi/products?_q=genre,retail_price&_a=g,p&p.gt=10&p.lt=20&g.eq=POP

There are two arrays: _q which lists the query parameters and _a listing the corresponding aliases. So p -> retail_price and g -> genres

I can parse this into:

{$and : [ genre: { '$eq': 'POP' }, retail_price: { '$gt': '10' }, retail_price: { '$lt': '20' } ]}

Almost happy. But there are a couple of problems with this approach: 1. the '$eq' etc instead of $eq etc 2. the numeric value is now a string '10'

I consider (2) to be a nasty one. Since the server cannot know the type (maybe it should be '10' instead of 10).

So, I want to try another approach. And that is parsing it all into a queryString and then convert that with JSON.parse()

First I put up some query string and try it in the shell:

db.products.find({$and: [{genre: { $eq: 'ROC'}}, {retail_price: {$gt:7}}, {retail_price: {$lt:10}}]})

Works like a charm.

Then I tried this:

var queryStr = "{$and: [{genre: { $eq: 'ROC'}}, {retail_price: {$gt:7}}, {retail_price: {$lt:10}}]}";

and: (Product is a mongoose model)

Product.find(JSON.parse(queryStr), function(err, product) {
    if (err)
        res.send(err);

        res.json(product);
    });

To my surprise it did not work at all.

Also doing

console.log(JSON.stringify(JSON.parse(queryStr)));

Does not write output to the console.

What is happening here?

1 Answer 1

1

The first thing is queryStr is not valid JSON. What you have is a string that looks like an object. But you might ask "isn't that JSON?". Short answer: no. Long answer: since JSON is a lightweight data exchange format it has to be readable by a variety of languages (not just Javascript). So quoting keys is a requirement to make this possible:

var json = '{"foo": true, "bar": 123}';
var str = '{foo: true, bar: 123}';
console.log(JSON.parse(json)); // Object {foo: true, bar: 123}
console.log(JSON.parse(str)); // SyntaxError: Unexpected token f

So, you could stringify the query object to JSON and then parse it before passing it to your mongoose method:

// On the client
var queryJSON = JSON.stringify({$and: [{genre: { $eq: 'ROC'}}, {retail_price: {$gt:7}}, {retail_price: {$lt:10}}]});
// On the server
var query = JSON.parse(queryJSON); // Object

That said, back to your original two concerns:

  1. Quoted key names: they have zero impact in this regard so they shouldn't be a concern at all.
  2. Incorrect value types: it looks like you already have a procedure for formatting the query to the correct object so you could use Number to coerce the string to a number value. (e.g. Number('10') // 10)
Sign up to request clarification or add additional context in comments.

2 Comments

Super! I can now indeed do what I wanted. Actually to let the server know that a number is indeed a number I've added a little syntax (e.g. p.eg=(10), instead of p.eq=10). It now works like a charm. I can now write stuff like: ../products?_q=genre,filling_rate,retail_price&_a=g,f,p&g.eq=ROC&f.eq=(95)&p.lt=(8)
I should add, that when using Mongoose with a schema, the addition of (..) is not needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.