Handling Optional Query Params in NodeJS API [duplicate] - javascript

I want to send in response some data according to searching by query parameters (using .find function of mongoose) from the client side. What do I need to do is a search according to the parameters received?
What I mean is :
I may receive
localhost:5000/admin/customers?customer_id=1&customer_email=abc#gmail.com
I could have used this code to send results according to this query :
Customer.find({
customer_id = req.query.customer_id,
customer_email = req.query.customer_email,
}, (err,docs)=> {
res.json(docs);
})
or
just
localhost:5000/admin/customers?customer_id=1
I could have used this code to send results according to this query :
Customer.find({
customer_id = req.query.customer_id
}, (err,docs)=> {
res.json(docs);
})
or
may be
localhost:5000/admin/customers?no_of_items_purchased=15
I could have used this code to send results according to this query :
Customer.find({
no_of_items_purchased = req.query.no_of_items_purchased
}, (err,docs)=> {
res.json(docs);
})
But what I want is to use .find function on anything received from query params. Like a general code to achieve this.
PS: Also please help with : "How to filter req.query so it only contains fields that are defined in your schema ?"

You can create a query variable to keep the field that you want to filter.
Suppose that your Customer model structure is:
{
customer_id: ...,
customer_name: ...,
customer_email: ...,
no_of_items_purchased: ...
}
Then your code will be:
let {customer_id, customer_name, customer_email, no_of_items_purchased} = req.query;
let query = {};
if (customer_id != null) query.customer_id = customer_id;
if (customer_name != null) query.customer_name = customer_name;
if (customer_email != null) query.customer_email = customer_email;
if (no_of_items_purchased != null) query.no_of_items_purchased = no_of_items_purchased;
let result = await Customer.find(query);

Just pass request.query as a parameter directly on find method:
Customer.find(request.query)

Related

Can you build a query in prisma without executing it?

I have a find method in my api that takes these parameters
-limit (optional)
-select (optional)
-sort (optional)
-skip (optional)
In MongoDB you can build a query like this :
let query = model.find(query);
if(limit) {
query.limit(limit)
}
if(skip) {
query.skip(skip)
}
// ....
let result = await query.exec();
Is there a similar option in Prisma ?
I am not Prisma user, but seems like you can build config parameters beforehand like
let query = {
skip: skip,
take: limit
};
prisma.model.findMany(query)

mongoosejs - find() using nested objects

question is possibly a duplicate but I haven't found anything that provides an appropriate answer to my issue.
I have an ExpressJS server which is used to provide API requests to retrieve data from a MongoDB database. I am using mongoosejs for the MongoDB connection to query/save data.
I am building a route that will allow me to find all data that matches some user input but I am having trouble when doing the query. I have spent a long while looking online for someone with a similar issue but coming up blank.
I will leave example of the code I have at the minute below.
code for route
// -- return matched data (GET)
router.get('/match', async (req, res) => {
const style_data = req.query.style; // grab url param for style scores ** this comes in as a string **
const character_data = req.query.character; // grab url param for character scores ** this comes in as a string **
// run matcher systems
const style_matches = style_match(style_data);
res.send({
response: 200,
data: style_matches
}); // return data
});
code for the query
// ---(Build the finder)
const fetch_matches_using = async function(body, richness, smoke, sweetness) {
return await WhiskyModel.find({
'attributes.body': body,
'attributes.richness': richness,
'attributes.smoke': smoke,
'attributes.sweetness': sweetness
});
}
// ---(Start match function)---
const style_match = async function (scores_as_string) {
// ---(extract data)---
const body = scores_as_string[0];
const richness = scores_as_string[1];
const smoke = scores_as_string[2];
const sweetness = scores_as_string[3];
const matched = [];
// ---(initialise variables)---
let match_count = matched.length;
let first_run; // -> exact matches
let second_run; // -> +- 1
let third_run; // -> +- 2
let fourth_run; // -> +- 3
// ---(begin db find loop)---
first_run = fetch_matches_using(body, richness, smoke, sweetness).then((result) => {return result});
matched.push(first_run);
// ---(return final data)---
return matched
}
example of db object
{
_id: mongoid,
meta-data: {
pagemd:{some data},
name: whiskyname
age: whiskyage,
price: price
},
attributes: {
body: "3",
richness: "3",
smoke: "0",
sweetness: "3",
some other data ...
}
}
When I hit the route in postman the JSON data looks like:
{
response: 200,
data: {}
}
and when I console.log() out matched from within the style match function after I have pushed the it prints [ Promise(pending) ] which I don't understand.
if I console.log() the result from within the .then() I get an empty array.
I have tried using the populate() method after running the find which does technically work, but instead of only returning data that matches it returns every entry in the collection so I think I am doing something wrong there, but I also don't see why I would need to use the .populate() function to access the nested object.
Am I doing something totally wrong here?
I should also mention that the route and the matching functions are in different files just to try and keep things simple.
Thanks for any answers.
just posting an answer as I seem to have fixed this.
Issue was with my .find() function, needed to pass in the items to search by and then also a call back within the function to return error/data. I'll leave the changed code below.
new function
const fetch_matches_using = async function(body, richness, smoke, sweetness) {
const data = await WhiskyModel.find({
'attributes.body': body,
'attributes.richness': richness,
'attributes.smoke': smoke,
'attributes.sweetness': sweetness
}, (error, data) => { // new ¬
if (error) {
return error;
}
if (data) {
console.log(data)
return data
}
});
return data; //new
}
There is still an issue with sending the found results back to the route but this is a different issue I believe. If its connected I'll edit this answer with the fix for that.

How to make mongo validate documents before insert or update in Vertx?

I'm newbie using Vertx, I'm building a basic Api Rest with Vertx + Mongo using Javascript.
I'm looking for some way to automaticly validate the incoming documents before insert or update (for example, something like schemas in Mongoose).
I got the following:
POST entry point Inserting a new cat
var BodyHandler = require("vertx-web-js/body_handler");
var Router = require("vertx-web-js/router");
var router = Router.router(vertx);
router.post("/cat")
.produces("application/json")
.handler(BodyHandler.create().handle)
.handler(controller.createCat);
Controller's function Inserting a new cat
createCat: function (ctx) {
var response = ctx.response();
var body = ctx.getBodyAsJson() || {};
console.log('inserting cat')
connection.mongoClient.insert("cats", { name: body.name }, function (res, res_err) {
if (res_err == null) {
var id = res;
console.log("Inserted cat with id " + id);
response.putHeader("content-type", "application/json");
response.end(JSON.stringify(id));
} else {
console.log('err')
res_err.printStackTrace();
}
});
}
The problem is that I can insert empty documents resulting documents with only one field: the mongo ID.
TL;DR - I want to know if there is some way to tell Mongo that name field is ALWAYS required.
Solution I used:
mongoClient.runCommand("collMod", { collMod: "cats", validator: { $and: [ {"name": {$type: "string", $exists: true}} ] }, validationLevel: "strict", validationAction: "error" }, function(res, res_err) {
if (res_err) res_err.printStackTrace()
else console.log('The schema of cats collection has been updated')
});
In mongodb there is a concept of validation with query filters for collection: https://docs.mongodb.com/manual/core/schema-validation/#query-expressions
If the "name" field is always required, you can create your collection like this:
db.createCollection("cats", {
validator: {
$and: [ {"name": {$type: "string", $exists: true}} ]
})
you can create your own schema in a separate json file, then create your own validation method when the context is provided by ur router.
I assume different endpoint has different validation.
you can also create a middleware using gateleen
you have plenty of options, mongoose its benefits but the whole point of using mongodb is not creating a schema. Therefore, u can assume that the request should have specific mandatory fields to validate.

Index data to ElasticSearch with Firebase functions, not all fields are indexed

I am using Firebase function to push data to ElasticSearch to be indexed. But sometimes the data set is not indexed completely. Which fields can be indexed seem to be a random behavior, sometimes all fields are indexed, sometimes only a few, sometimes only one.
The firebase function I used to push data to Elastic search as below:
exports.indexHashtagsToElastic = functions.database.ref('/valid_hashtags/{hashtag_id}')
.onWrite(event =>{
let hashtagData = event.data.val();
let hashtag_id = event.params.hashtag_id;
console.log('Indexing the hashtags: ', hashtagData);
let elasticSearchConfig = functions.config().elasticsearch;
let elasticSearchUrl = elasticSearchConfig.url + 'hashtags/hashtag/' + hashtag_id;
let elasticSearchMethod = hashtagData ? 'POST' : 'DELETE';
let elasticSearchRequest = {
method: elasticSearchMethod,
url: elasticSearchUrl,
auth:{
username: elasticSearchConfig.username,
password: elasticSearchConfig.password
},
body: hashtagData,
json: true
};
return request(elasticSearchRequest).then(response => {
console.log("ElasticSearch response", response);
});
});
according to this log console.log('Indexing the hashtags: ', hashtagData); sometimes the dataset is not coming through in full. However the dataset created on database is complete and correct.
Any idea what went wrong here? Thanks!
You need to specify the fields to index on your request.
let elasticSearchFields = ['field1','field2','field3',...'fieldn'];
Then in your request you should add the following
...
body: _.pick(hashtagData , elasticSearchFields ),
...
Hope that will work

Get unique id of specific element in Firebase

I have my Firebase database structured like this:
{
"userProfile" : {
"X0u2SEFfYEeVmdw4TXl58ou2eYy1" : {
"email" : "jane#yahoo.com",
"name" : "Jane"
},
"cliv7hQ4FsWKTtYksPDXcdDafdi2" : {
"email" : "doe#gmail.com",
"name" : "John Doe",
}
}
}
I'm trying to get the unique id of the element that matches query criteria, for example the key of the element with email equal to doe#gmail.com.
I'm doing this by using:
firebase.database().ref('/userProfile').orderByChild('email').equalTo(email).once( 'value', data => {
let user = data.val();
});
This returns me the entire object with that email, but I only want its unique id ("cliv7hQ4FsWKTtYksPDXcdDafdi2" in this case). What's the best way to achieve this?
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
So:
var query = firebase.database().ref('/userProfile').orderByChild('email').equalTo(email);
query.once( 'value', data => {
data.forEach(userSnapshot => {
let user = userSnapshot.val();
let key = userSnapshot.key;
});
});

Categories

Resources