Comparing field values in MongoDB - mongodb

I wanted to run a query that finds the following document from MongoDB database
{field1:"foo",field2:"barfoobar"}
I know for equality I can use the following query:
.find({ $where : "this.field1 == this.field2" })
In C#
new BsonDocument("$where", new BsonJavaScript("this.field1 == this.field2"));
But how I can use regex in above query?
Somthing like:
.find({ $where : "this.field1 like this.field2" })
And in C# ?

Use the following query and check if it works for you. Let me know if it helped:
db.col.find( { $where: function() {
var regex = new RegExp(this.field1);
return (regex.test(this.field2))
} }).pretty();
The query above turns foo into a regex (something like /foo/) and checks if field2 matches the regex you passed.
FYI: The following statement was taken from mongodb website. Take it into consideration:
Changed in version 3.6: The $expr operator allows the use of aggregation expressions within the query language. $expr is faster than $where because it does not execute JavaScript and should be preferred where possible.

Related

Is there a way for using $where operator to get data that contains specified strings in MongoDB?

Current JSON object is
{"_id":{"$oid":"613ed8098709b6402ab91ddd"},"employeeid":1187,"name":"John Steight","salary":75000},
{"_id":{"$oid":"613ed8788709b6402ab91dde"},"employeeid":2455,"name":"Syed","salary":90000},
{"_id":{"$oid":"613ed8c78709b6402ab91ddf"},"employeeid":24113,"name":"Wright John","salary":65000}
Use the $where operator to find employees where the name contains John
Here is my command:
db.HR.find({$where: "this.name == /$John$/"}).
It returned nothing.
If want to use $where, you should pass it a valid JavaScript expression. You can do it like this:
db.collection.find({
$where: "this.name.includes('John')"
})
Working example
Note that you don't have to use $where. You can do it with $regex, like this:
db.collection.find({
name: { "$regex": "John" }
})
Working example

Use $in operator to match regex in mongoengine

Following the MongoDB documentation, you can use the $in operator with a regular expression like wise db.inventory.find( { tags: { $in: [ /^be/, /^st/ ] } } ). Is there a way to achieve the same result using mongoengine?
For example pass {"tags__in": ["/^be/", "/^st/"]} to my query?
I don't think this is supported by MongoEngine in normal query construct (i.e I doubt that Doc.objects(tags__in=["/^be/", "/^st/"] will work)) but there is support for __raw__ query (https://docs.mongoengine.org/guide/querying.html#raw-queries)
so the following should work
Inventory.objects(__raw__={"tags": { "$in":["/^be/", "/^st/"]}})

Mongo: Find docs where field is a prefix of a string literal without using $where

I want to find all documents where a given field is a prefix of an input value. In SQL it looks like this:
... where input_value like concat(field, '%')
I want to do this in Mongo 2.4.8 (very much preferably) without using $where. It's easy with $where but I can't use $where because I want to use a pipeline so I can use $project to derive some fields. And apparently you can't use $where in pipeline a $match. And as far as I can see you can't use the pipeline $project-ion operators in a normal find() projection - argh.
One way of doing it would be to construct a $regex pattern. The below example demonstrates the construction and usage of a regexp. There are alternative ways one could build a regexp.
sample insert scripts:
db.t.insert([
{"name":"sampleString"},
{"name":"sam"},
{"name":"s"},
{"name":"sample"}
])
sample code:
var input = "sample";
var pattern = ''
input.split('').reverse().forEach(function(i,j){pattern = '('+i+pattern+')?'}) // (s(a(m(p(l(e)?)?)?)?)?)?
var regexp = new RegExp("^"+pattern+"$");
and use it as:
db.t.find({"name":{$regex:regexp}});
or:
db.t.aggregate([
{$match:{"name":{$regex:regexp}}}
])
That would give you:
{ "_id" : ObjectId("56cba179d99d86bcb7251107"), "name" : "sam" }
{ "_id" : ObjectId("56cba179d99d86bcb7251108"), "name" : "s" }
{ "_id" : ObjectId("56cba19fd99d86bcb725110c"), "name" : "sample" }
And as far as I can see you can't use the pipeline $project-ion operators in a normal find() projection - argh.
You can definitely, use project fields in a find() statement as below, though you cannot modify the projected field.
db.t.find({"name":{$regex:regexp}},{"fieldToProject":1});

How to sort by the value of number1 plus number2 in the mongodb

I prepare get some objects in the mongodb.
{number1:123,number2:321}
{number1:222,number2:4532}
For example, these are what i have in the database. But now, i want to get them by the value of number1 + number2.
How to do it ?
One option that no one has actually said here is to use the aggregation framework. Better than using $where since it will be faster and you can actually sort on that return and more as such:
db.c.aggregate([
{'$project': {sumField: {$add: ['$number1', '$number2']}}},
{'$sort': {sumField: 1}}
]);
Like so. Better than using the inbuilt JS, plus with an index and covered query you could make this faster since aggregation, unlike $where can actually use an index.
Use $where operator
db.myCollection.find( {'$where':'this.number1 + this.number2 = 200'})
Adding a virtual to your schema in mongodb will help you
YourSchema.virtual('numbersum')
.get(function () {
return this.number1 + ' ' + this.number2;
})
Then, you´ll be able to do that:
db.yourcollection.find().sort({numbersum:1});
Check this answer. Sorting by virtual field in mongoDB (mongoose)
EDIT this will work only when using mongoose as connector

MongoDB: Perform a text-search in a document field (using high-level API)

It may be related to this question
Basic GROUP BY statement using OPA MongoDB high level API.
I want to be able to retrieve a list of documents which "name" field value contains a given string.
Here's my documents list :
{name: "Charles-Hugo"},
{name: "Jean Pierre"},
{name: "Pierre Dupont"},
I want to be able to only retrieve documents which name contains the "Pierre" string: Jean Pierre, and Pierre Dupont.
I know this isn't possible with the MongoDB high-level API.
I've looked in the low-level API functions but I don't know what's the easiest way to retrieve my documents in safe Opa type.
Also I'd like to add skip/limit options to my query.
Any idea ?
The DbGen automation mechanism in Opa has support for this:
DbSet.iterator(/path/data[name =~ pattern])
As #Henri pointed out there is regular expression searching support in Opa since commit [enhance] DbGen: add case insensitive regex operator =~ what is very nice.
Mind that it is using $regex operator, not the full-text index and it may result with some performance loss :( As MongoDB documentation says $regex operator uses indexes in limited way - only for prefix search: pattern ^Jean. Searching for Jean anywhere in text will require full scan.
Personally, I am using full-text index feature of Mongo with Opa's "low-level" API for the $text command like this:
function list({float score, Article.id id}) textSearch(string query) {
function onfailure(failure) {
cat.error("textSearch({{~query}}): {failure}");
[];
}
function onsuccess(success) {
function aux(~{name,value}) {
name == "results";
}
match (List.filter(aux, success)) {
| [] :
// `results` field not found - error
onfailure(success);
| results:
cat.debug("textSearch({~{query}}): {results}");
function ({~score, obj: ~{id}}) {
~{score, id}
}
|> List.map(_, Bson.doc2opa(results) ? []);
}
}
opts = [H.str("search", query), H.doc("project", [H.i32("_id",0), H.i32("id",1)])];
// { search: query, project: {_id:0, id:1}, }
// |> Bson.opa2doc
outcome = MongoCommands.simple_str_command_opts(ll_db, db_name, "text", coll_name, opts);
MongoCommon.outcome_map(outcome, onsuccess, onfailure)
}
Feature is available in Mongo since 2.4 as experimental (you have to turn it on by special configuration option) and in 2.6 as stable (turned on by default).