How do I make a conditional query to a mongodb database? - node.js

I'm trying to make a filtering component for my website and I want to be able to get that data which they specified through the filter from the MongoDB database. I'm using MERN stack and want to conditionally send a query to the database to retrieve based on whether or not it's empty or not. If it's empty, it means the user wants anything in that specific category and not one specific thing so I don't want to send an empty query to the DB which is just going to look for an empty string/array and realize that nothing in the DB has an empty string/array and won't return anything.
That's why I want to conditionally render my query parameter because that's the only workaround I can think of for my earlier question which does not have a solution for:
How can I send an object as a query and use the $all operator in MERN stack?
Here is the code and where I want the the conditional render to happen:
var t = ["People"]
const test = await Project.find( {$all: {
theme: t // have something that condditionally sends this, if t is empty then don't send it
}}
).sort({ createdAt: -1 })
console.log(test)

You can conditionally construct the search-filter:
const filter = {};
if (t.length) { // or whatever condition you need
filter.$all = {theme: t};
}
const test = await Project.find(filter) // rest of your code

Related

Is there a way to filter through data based on if a search query is present in the string in mongodb?

I have data that looks like this in my mongoDB atlas database:
object: {
keywords: ['Homelessness', 'Food', 'Poverty']
}
I'm creating a filtering component for my MERN stack website and wanted to add a search feature for keywords like these that are present in each object in the database. If a search query was Homelessness for example, then the object above would show up since it has Homelessness as one of its keywords. But say for example I enter Homeless as a search query, the ones with Homelessness won't pop up because Homeless =/= Homelessness. Is there a way to somehow find if the search query is within a string inside an array which is all inside a json object?
Here is what I tried so far which gets the result I described in the situation above:
const getFilteredProjects = async (req, res) => {
// Initializing request object that will be sent to retrieve DB information
var request = {}
if (req.query.keywords !== '') {
request["keywords"] = req.query.keywords
}
console.log(request)
const projects = await Project.find(request).sort({ assignment_type: 1 })
res.status(200).json(projects)
}
How can I somehow access each string inside the keywords array and see if the search query is present in it? Is that possible with mongodb or would I have to somehow do it through javascript? If that's the case I'm not sure how I could do that, I would appreciate it if I could get some help.

mongoose - select specific fields in Model.create

const generatedEvent = await Event.create(req.body);
res.send(generatedEvent);
I am getting some data from the request body and I can generate a new Event. And I'm returning the event to client when it has generated. But I don't want to return all fields with event. I want to make filter operation like how we are using select function like this: Event.find().select({title:1,description:1})
How can i use this select func with Model.create?
If you take a look at the mongoose-source code, you can see that Model.create returns a promise with the created/inserted documents. There's no way to specify a filtering-options to return only specific fields.
Of course you could do a .find() in combination with a .select() call after creating/inserting a new record but that would result in one extra DB-query for each insert which does not make a lot of sense.
You could instead just return the desired properties from the returned document, since you know that a new document was inserted successfully with the provided data, when the promise resolved. So you could simply do:
res.send({title: generatedEvent.title, description: generatedEvent.description});
Model.create() internally doesn't fetch the document from the database, rather it actually returns the result whether it's inserted successfully or not. If successful, mongoose will return the original mongoose document that mongoose created before sending to the database.
So you could just select the fields by yourself. Using es2015 Object destructuring assignment and Object shorthand property names would help writing more concise code.
const { title, description } = await Event.create(req.body); // Object destructuring
res.send({ title, description }); // Object shorthand property names

How can I limit the result to a field with array that has a specific value?

I want to display a single article only with those comments (it is an array) which have the approve value set to "true" in my database. I can't get the correct result. Here is my backend code. I use pure MongoDB, without Mongoose.
app.get("/posts/:id", function (req,res) {
blog.collection("posts").findOne({"_id":ObjectId(req.params.id)}
,function (error,post )
{
res.render("user/post",{post:post});
});
});
Here is what my database looks like, I want to filter or limit the result to comment approve = "true".
Thank you very much for every answer.
I don't know if there is better solution but it can be obtained by this:
let newPost = {...post}
newPost.comments = newPost.comments.filter(comment=>comment.approve)
res.render("user/post",{post:newPost});

Sails.js: How to find records based on values in associated collection?

I'm looking for a way to make sub-query using Sails.js Waterline. The record has an association with Charge model.
I would expect something like that to work, but that doesn't seem to be supported:
var topRecords = await Record.find({'charge.paid':true});
The closest I got was this:
var topRecords = await Record.find().populate('charge',{paid:true});
but the problem is that it still returns all the Records regardless, just doesn't populate the records that do not match populate where statement.
The reason why I can't search for charges first is that I want to sort the data based on one of the values in Record.
You can fetch the Charges then use .map to get the records from there.
const topCharges = await Charge.find({ paid: true }).populate('records');
const topRecords = topCharges.map(charge => charge.record);

Validate a mongodb query syntax programmatically

I have an API method where the user can pass in their own query. The field in the collection is simply ns, so the user might pass something like:
v.search = function(query: Object){
// query => {ns:{$in:['foo','bar',baz]}} // valid!
// query => {ns:{$in:{}}} // invalid!
// query => {ns:/foo/} // valid!
});
is there some way to do this, like a smoke test that can fail queries that are obviously wrong?
I am hoping that some MongoDB libraries would export this functionality... but in all likelihood they validate the query only by sending it to the database, which is in fact, the real arbiter of which query is valid/invalid.
But I am looking to validate the query before sending it to the DB.
Some modules that are part of MongoDB Compass have been made open source.
There are two modules that may be of use for your use case:
mongodb-language-model
mongodb-query-parser
Although they may not fit your use case 100%, it should give you a very close validation. For example npm install mongodb-language-model, then:
var accepts = require('mongodb-language-model').accepts;
console.log(accepts('{"ns":{"$in":["foo", "bar", "baz"]}}')); // true
console.log(accepts('{"ns":{"$in":{}}}')); // false
console.log(accepts('{"ns":{"$regex": "foo"}}')); // true
Also may be of interest, npm install mongodb-query-parser to parse a string value into a JSON query. For example:
var parse = require('mongodb-query-parser');
var query = '{"ns":{"$in":["foo", "bar", "baz"]}}';
console.log(parse.parseFilter(query)); // {ns:{'$in':['foo','bar','baz']}}
I don't think it's possible to do otherwise than by reflecting query.ns object and checking every of its property / associated value

Resources