Invalid Regex Mongoose - node.js

I am new to MongoDB and I need to apply a regex to the find method using NodeJS Mongoose. The db contains elements such as:
{
"_id" : ObjectId("1234567899788675432454677"),
"nodes" : "[{\"name\":\"BINS\",\"oxygenation\":7.8,\"oxygenSaturation\":86,\"temperature\":13.3},{\"name\":\"CEST\",\"oxygenation\":4.6,\"oxygenSaturation\":52,\"temperature\":14.7},
"orp" : "0",
"chlorophyll" : "0",
"date" : "1615995776000",
"__v" : 0 }
and I need to go inside the nodes string to get all "name" values (in the example BINS and CEST). The regex that allows me to do it is
/(?<=name\\\"\:\\")\w+(?=\\)/gm
but I get errors when trying to use it both in mongo and Mongoose. For mongo I tried to escape all special characters:
db.my_collection.find( { nodes: { $regex: "\(\?<=\\\"name\\\": \\\"\)\\w\+\(\?=\\\\\)" } } )
but I get an empty result.
On Mongoose I tried several escaping such as the following, but I always get an error of invalid regex.
db.my_collection.find({ nodes : { $regex : '\(?<=name\\\\\\\"\\:\\\\\"\)\\w+\(?=\\\\\)' } }).
exec(function (err, waterSensorsReadings) { ... });

Related

mongoose return null in the query

my mongodb has a collection with data like this
{
"_id" : ObjectId("62ead2a8dd6922cfd6f466e4"),
"t" : "d",
"u" : {
"_id" : ObjectId("621d3469dd01e282b9a62321"),
"username" : "helxsz"
},
"users" : [
ObjectId("621d3469dd01e282b9a62321"),
ObjectId("628ee99ed0a58e00496a0730")
],
"createdAt" : ISODate("2022-08-03T19:55:20.965Z"),
"updatedAt" : ISODate("2022-08-03T19:55:20.965Z")
}
I am using node.js and mongoose to query the document.
let query = {
u:{
_id: "621d3469dd01e282b9a62321",
username: "helxsz"
},
t:'d',
};
collection
.findOne(query, 'u t ')
.exec(getResult);
why the executed query returns null to me
Maybe is because in your DB the u._id is ObjectId and in your query is a string. Mongoose should (?) parse it but I've faced not-parsed error like this many times.
So try parsing to ObjectId, in this example works.
Also an other problem is trying to search an object like this:
{
u:{
_id: "621d3469dd01e282b9a62321",
username: "helxsz"
}
}
Because in this way mongo looks for by the objects with the same order. You have to use dot notation
As an example, check how this query not work all times. To ensure the result you have to use dot notation:
let query = {
"u._id": "621d3469dd01e282b9a62321", // maybe casting to ObjectId is necessary
"u.username": "helxsz",
t: "d"
}
Example here
More info about Match an Embedded/Nested Document

How can I do multiple queries to mongo at one request

Let say I have a collection of Person{email: 'actual email', ..other data} and want to query if Person exists with given email and retrieve it data if so or get a null if not.
If i want to do that once than no problem just do a query, through mongoose using Person.findOne() or whatever.
But what if I have to do a check for 25-100 given emails? Of course I can just send a tons of requests to mongodb and retrieve the data but it seems a vast of network.
Is there a good and perfomant way to query a mongodb with multiple clauses in single batch like findBatch([{email: 'email1'}, {email: 'email2'}...{email: 'emailN'} ]) and got as result [document1,null,document3,null, documentN] where null is for not matched find criterias?
Currently I see only one option:
Huge find with single {email: $in: [] } query and that do a matching through the searching on the server side in application logic. Cons: quite cumbersome and error prone if you have more than one search criteria.
Is there any better ways to implement such thing?
Try this:
Replace the arrayOfEmails with your query array
Replace emailField with the actual name in your db documents
db.collName.aggregate([
{
"$match" : {
"emailField" : {
"$in" : arrayOfEmails
}
}
},
{
"$group" : {
"_id" : null,
"docs" : {
"$push" : {
"$cond" : [
{
"$in" : [
arrayOfEmails,
[
"$emailField"
]
]
},
"$$ROOT",
null
]
}
}
}
}
])

mongoose $match wont return document

I use two ways to retrieve documents from my collection, the first one:
db.comments.find({"nid" : "req.body.data"});
returns many doc like:
{
"nid" : 20404,
"_id" : ObjectId("5638ba331294943d3d0a092b"),
"uid" : 1937,
"posted" : ISODate("2015-11-03T13:44:19.811Z"),
"text" : "txt",
"title" : "Test nid 2",
"stars" : 3,
"__v" : 0
}
,
And for another query I need to use aggregate and the query:
var pipleline = [
{$match: {nid:req.body.data}}
];
Comments.aggregate(pipleline, function(err, rank){
if(err) {
res.send("Error", String(err));
}
res.send(rank);
});
Returns [] - empty array.
Any ideas?
You can use the built in function chaining mongoose provides. Aside from match, it also has sort, project, group, and few others I don't know off the top of my head. More info here
Comments.aggregate().match({nid:req.body.data})
.exec(function(err,rank){
if(err) {
res.send("Error", String(err));
}
res.send(rank);
});

MongoDB full text search on string array

So I'm using Node.js with MongoDB for my web application. I'm having some trouble creating a text index for my schema and searching for text within an array. I've looked at the mongo docs but haven't found anything related to this specifically.
My current implementation searches successfully on regular String values, but querying for text matching in [String]'s don't return anything.
Here's my REST call:
...console.log("Query string: " + str);
var qry = {
"$text": {
"$search": str
}
};
model.find(qry, function (err, results) {...
And when I create my schema:
var blah = new Schema({
foo : String,
bar : [String],
...
blah.index({
foo: 'text',
bar: 'text'
});
Any query won't return the results that match in bar. A query string for something within foo works fine.
Double check that you've created the correct indexes on the correct collections and the queries are being issued to the correct collections. Indexing an array works for me:
> db.test.drop()
> db.test.insert({ "_id" : 0, "a" : "dogs are good" })
> db.test.insert({ "_id" : 1, "a" : "I like dogs", "b" : ["where's my dog?", "here, have a cat"] })
> db.test.insert({ "_id" : 2, "b" : ["she borrowed my dog", "my frogs are croaking"] })
> db.test.ensureIndex({ "a" : "text", "b" : "text" })
> db.test.find({ "$text" : { "$search" : "dogs" } }, { "_id" : 1 })
{ "_id" : 0 }
{ "_id" : 2 }
{ "_id" : 1 }
Okay, I finally figured it out! Turns out, grunt serve doesn't update indexes in the database. I had created a text index for "foo" only and that didn't update when I added "bar" to the index. I had to run - in mongo shell:
db.dropDatabase()
The next time I ran it, the database was recreated and the proper indexes were set. If anyone else runs across this issue, try running db.getIndexes().

How to query parent based on subdocument's _id?

consider the following records:
user record
{
"_id" : ObjectId("5234ccb7687ea597eabee677"),
"class" : [
{ "_id" : ObjectId("5234ccb7687ea597eabee671", "num" : 10, "color" : "blue" },
{ "_id" : ObjectId("5234ccb7687ea597eabee672", "num" : 100, "color" : "blue" }
]
}
this user has two class sub records, now I need a query that finds all users that have class property where "class._id" has a value of at least one users "class._id"
here is a more detail example:
suppose there is four user:
A:{_id:432645624232345,class:[{_id:123,name:'foo'}]}
B:{_id:432645624232555,class:[{_id:555,name:'foo'},{_id:123,name:'foo'}]}
C:{_id:432645344232345,class:[{_id:555,name:'foo'},{_id:111,name:'www'}]}
D:{_id:432644444232345,class:[{_id:222,name:'sss'},{_id:555,name:'www'},{_id:123,name:'foo'}]}
now if B login , I need to query all the user whose class subdocument contains at least one document which's _id==555 or _id==123 (555 and 123 come from B user), in this case the query result should be:
A:{_id:432645624232345,class:[{_id:123,name:'foo'}]} // match _id=123
B:{_id:432645624232555,class:[{_id:555,name:'foo'},{_id:123,name:'foo'}]} //match _id=123 and _id=555
C:{_id:432645344232345,class:[{_id:555,name:'foo'},{_id:111,name:'www'}]} //match _id=555
D:{_id:432644444232345,class:[{_id:222,name:'sss'},{_id:555,name:'www'},{_id:123,name:'foo'}]} ///match _id=123 and _id=555
which is all the user.
so far i get this:
{"class._id" : { $in : ["5234ccb7687ea597eabee671", "5234ccb7687ea597eabee672"] } }
but when different user login the class._id query condition is different. So is there any operator to do this
{"class._id" : { $in : req.user.class } }
hope I made myself clear.
In order to achieve what you want, first you must isolate the class _ids in an array, and then use it in the query argument.
var classIds = [];
var i = 0;
while (i < req.user.class.length) {
classIds.push(req.user.class[i]._id);
i++;
}
After that you can use classIds array in the query:
{"class._id" : { $in : classIds } }
The following query condition would give you all the users that have at least one class with id equal to any of the elements in the given array:
{"class._id" : { $in : ["5234ccb7687ea597eabee671", "5234ccb7687ea597eabee672"] } }
In the array for the $in clause you may provide any id's you needed , comma separated.
In addition, if you needed such, the below query condition should check for existence of nested document within "class" property that has a property "_id" :
{ "class._id" : { $exists : true } }
Both conditions should work no matter if "class._id" is a single-valued property or an array (mongo supports that).

Resources