I have several documents in a collection in MongoDB as shown in this snapshot . I'm creating a web app for which this is the back-end data.
Every document has an attribute name. The user has an option to search for the name in the front-end. Now, suppose the user searches for "Sam", then I'm returning the documents where name is either exactly "Sam" or starts with "Sam". I have implemented this using the following code:
let name = "^"+req.body.name;
const name_regex = new RegExp(name, 'gi');
try {
let members = await Member.find({ name: req.body.name=="" ? /^$|/ : name_regex});
res.send(members);
}
i.e., if the user dosen't provide a name, return all documents, else return documents matching the regex.
So , if the user searches for "Sam", the output is all 3 documents since all of them have name starting with "Sam", but if the user searches for "Samm", then only one document is returned where the name is "Sammy".
Now, I want to implement the same logic on age attribute, i.e., if the user searches for age: 2, then I want to return all documents where age is either exactly 2 or starts with the digit 2. But I'm unable to use the above method sine it only works with strings.
Note: I'm using mongoose package and Express framework.
You can do this:
// regular expression matching anything that starts with two
const age_regex = /^2/;
Member.find({
$expr: {
$regexMatch: {
input: {
$toString: "$age" // Casting the age value to a string
},
regex: age_regex
}
}
})
Some usefule explanatory links: $expr, $regexMatch, $toString
Related
I have a mongoose schema as such:
const userSchema = new mongoose.Schema({
keywords: [{ "type": String, "enum": ["yup", "nope"] }],
})
Here, I have one user with a set of keywords and I want to find the records in my database which have the most similar set of keywords to this particular user.
For example, If a user has ["yup" "nope"] as their keywords, I want to find all records of users who have "yup" or "nope" or both in their keywords array. This is just an example and in reality, the users will have a whole lot more keywords to choose from.
How can I do this using mongoose?
I was thinking about one-hot-encoding the values in the array and the records with the most matching 1s can be added to another table "Most similar values table or something" that maintains this list for every user with the user as the foreign key. But I haven't been able to come up with an efficient and/or working algorithm for this yet.
In my opinion the best aproach is regular expresion. I write you one example function how to search and filter data in MongoDB using mongoose. For example lets search customers by lastName example for starts, ends, contains string "yup". Be aware searching with regex is case sensitive default. If you add "i" after regex it will be case insensitive.
async function getCustomers() {
const customers = await Customer
//case search lastName whitch starts with "yup" - case sensitive
.find({lastName: /^yup/})
//or case search lastName whitch ends with "yup" - case insensitive
.find({lastName: /yup$/i })
//or case search lastName whitch contains "yup" in any part
.find({lastName: /.*yup.*/ })
.limit(20) //get top 20 results
.sort({lastName: 1}) // sort by lastName
console.log(customers)}
//searching in array
const customerList = ['Smith', 'Jackson'];
async function getCustomers(arr) {
return await Customer
.find({lastName: {$in: arr}})
.limit(20) //get top 20 results
.sort({lastName: 1}) // sort by lastName
}
getCustomers(customerList);
for more info chceck documentations:
https://docs.mongodb.com/manual/reference/operator/query/regex/
I have been trying to use https://github.com/wearetheledger/node-couchdb-query-engine for querying the couchdb based on the selector query which would be supplied by the UI based on the action the user makes.
the code below used in the library takes cars as a constant which in my case need to be on the actual couchdb. the secord parameter (the selector one would be supplied from the UI)
const filteredResult = queryEngine.parseQuery( cars, {selector:{year:{$gt:2016}}} )
The main issue is i want the first parameter (cars here) to be a kind of db connection on which the selector query gets applied.
Regards,
Saurabh
The code you're trying to use is just providing a SearchInterface on a Javascript object.
If you want to use dynamic queries on CouchDB, you can do it natively with the Mango.
Since you're using NodeJS, you could use the official NodeJS library client for CouchDB:
Nano: https://github.com/apache/couchdb-nano
Code example:
const nano = require('nano')('http://localhost:5984');
nano.db.create('alice');
const alice = nano.db.use('alice');
/ find documents where the name = "Brian" and age > 25.
const q = {
selector: {
name: { "$eq": "Brian"},
age : { "$gt": 25 }
},
fields: [ "name", "age", "tags", "url" ],
limit:50
};
alice.find(q).then((doc) => {
console.log(doc);
});
This question already has answers here:
MongoDB: Is it possible to make a case-insensitive query?
(27 answers)
Closed 3 years ago.
So, I want to add a search bar to my web application and I want to display the users when I enter names inside my input element.
I filter out the names on the back-end by creating a mongodb query and at the $regex I enter the string that the user entered in the input element (search bar) on the front-end. I thought it was working fine, but now my boss says that many users simply aren't showing up when he enters their name. I went through the entire thing and it has gotta have something to do with the regex I enter in the MongoDb query.
For example when I enter 'jonas' in the search bar I would expect that this would return the document of the user with the full_name property value Jonas Rodrigo. Am I wrong to think I can simply enter the input element string like I did below? And if so, how can I improve it?
So this is what it looks like: when I enter the name Jonas I expect this user to show, but unfortunately he doesn't show up.
this is my mongoDB query function: I simply enter the string ('jonas' in this case) into the $regex, but I must be doing something wrong because it doesn't return the desired user (the other two conditions are truthy)
const createUserQuery = (user, query) => User.find({
$and: [
{ full_name: { $regex: query, $options: 'i' } },
{ _workspace: user._workspace },
{ active: true }
]
}).select('profile_pic full_name email created_date');
example mongodb user document
The problem may be with your regular expression query.
If you want to search for all names starts with Jonas
The value of the query parameter you pass to the createUserQuery should be like
^Jonas
^ is the key here to get all names start with Joans
As #Mani has said, perhaps it's an issue with your RegEx. You could try something like this expression against your query: const regex = new RegExp(query, 'g').
For example, if query = Jonas, the RegEx should match documents with a full_name property containing "Jonas Rodrigo".
const regex = new RegExp(query, 'g');
const createUserQuery = (user, query) => User.find({
$and: [
{ full_name: { $regex: regex, $options: 'i' } },
{ _workspace: user._workspace },
{ active: true }
]
}).select('profile_pic full_name email created_date');
Is there a (proper) way to use the $oroperator in a URL query string to realize a client customizable query which does not only consist of and combined fields against my node.js powered RESTful API?
Let's say I have objects like
[{
A: 1,
B: 2,
C: 42
}, {
A: 3,
B: 1,
C: 42
}]
How do I query the MongoDB using mongoose to get both of them if searched in multiple fields? Something like $and: [{C:42}, $or: [{A:1}, {B:1}]] as URL parameters?
I tried GET /api/orders?$or=[{A:1},{B:1}]], but that results in a query like orders.find({ '$or': '[{A:1},{B:1}]]' }}), where the array is a string. The MongoDB driver then complains about $or needs an array.
All libraries like mongo-querystring have some complex operators for $gtand so on, but not for a simple OR of parameters. What am I missing here?
My goal is to build a convience search field, where the user can enter a simple string which then in turn is searched in multiple fields, returning all documents where at least one field (or a substring of that field) matches. So the frontend should decide in which fields and how the server should search, leading to a dynamic set of AND/OR combined field/value pairs.
Thanks in advance,
Ly
One option is to use the qs library which is a querystring parser with nested object support.
const qs = require('qs');
const query = {$or:[{A:1},{B:1}]};
let stringQuery = qs.stringify(query);
console.log(stringQuery); // => %24or%5B0%5D%5BA%5D=1&%24or%5B1%5D%5BB%5D=1
console.log(qs.parse(stringQuery)); // => { '$or': [ { A: '1' }, { B: '1' } ] }
I need to make the following query, I have a model in the db that holds a string. for example lets say that's the data:
[{ a : 'test/t' },
{ a : 'test/b' }]
Now I have the following string
var search = 'http://ttt.com/test/t'
I want to make a query which will find all the documents that 'a' property is contained inside the search variable, case insensetive.
All the exmaples I've seen talk about the opposite equation.
You can use the following query for the operation which uses the short for $where. Since this runs in Javascript, expect it to run slowly.
db.coll.find(function () {
var re = new RegExp(this.a.replace("/", "\/"))
return 'http://ttt.com/test/t'.match(re)
});