Search code examples
javascriptarraysmongodbfaceted-searchrest-parameters

Express JS unlimited query parameter function?


I'm trying to set an unlimited query parameter in express js.But I couldn't figure out how should I implement that in my code. I'm using MongoDB aggeration

I want to build unlimited facets searched with multiple $match stage


Which works like this:

'http://localhost:4000/search?text=mango'
'http://localhost:4000/search?text=mango&key=brand&value=rasna' //unlimited facets.
'http://localhost:4000/search?text=mango&key=brand&value=rasna&key=color&value=yellow'  //unlimited facet parameters

Here's my code to do this:

app.get("/search", async(request, response) => {
    try {
        const textsearch = request.query.text;

        var keystore = request.query.key;      //storing `key` in 'keystore'
        var valuestore = request.query.value;  //storing `value` in `valuestore`

        if (keystore, valuestore) {

            facetjson = [
             {
                '$match': {
                    [keystore]: `${valuestore}`  //Storing key and value in $match
                }
             }
           ]

            const Pipeline = [{
                    '$search': {
                        'text': {
                            'query': `${textsearch}`,
                            'path': 'title',
                        }
                    }
                },
                {
                    '$limit': 5
                }
            ]

            //Pushing 'facetjson' array into Pipeline array to make a filtered search possible.

            const newitem = insert(Pipeline, Pipeline.length - 1, facetjson) 

            let result = collection.aggregate(newitem).toArray();
            response.send(result);
        } else {
            const Pipeline = [{
                    '$search': {
                        'text': {
                            'query': `${textsearch}`,
                            'path': 'title',
                        }
                    }
                },
                {
                    '$limit': 5
                }
            ]
            let result = collection.aggregate(Pipeline).toArray();
            response.send(result);
        };
    } catch (error) {
        response.status(500).send({ message: error.message });
    }
})

(JSFIDDLE code Example)[https://jsfiddle.net/divyanshuking/z0vo589e/]

==> I know that I've to pass $match in the Pipeline array each time for single Key , Value Pair. Doing many google searches I've figured out that I've to use the Rest Parameter (...keystore,...valuestore). But I didn't know how to implement this. Have you guys any better idea to do solve this problem? Pls help me:


Solution

  • Your request URL has a wrong structure for query parameters. If you want to pass multiple kay/value pairs in URL, the correct structure is like this:

    • 'http://localhost:4000/search?text=mango&brand=rasana&color=yellow

    This code should work with this URL structure:

    app.get("/search", async(request, response) => {
        try {
            //We need "search pipeline stage" in all conditions. whether we got a key/value pair in query or not. 
            //so we use "search stage" when declare pipeline array;
            let pipeline = [{
                '$search': {
                    'text': {
                        'query': `${request.query.text}`,
                        'path': 'title',
                    }
                }
            }];
            //If there are keys/values pairs in the query parameters, we add match stage to our pipeline array;
            if(request.query) {
                let match = {}, hasMatchSatge = false;
                for(let item in request.query){
                    if(item !=== 'text'){
                       match[item] = request.query[item];
                       hasMatchStage = true;
                    }
                }
                if(hasMatchStage) pipeline.push({'$match': match});
            }
            //Finally, we add our "limit stage" to the pipeline array;
            pipeline.push({'$limit' : 5});
            let result = collection.aggregate(pipeline).toArray();
            response.status(200).send(result);
        } catch (error) {
            response.status(500).send({ message: error.message });
        }
    

    })