Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use regex inside in query using morphia?

Mongodb allows regex expression of pattern /pattern/ without using $regex expression.

http://docs.mongodb.org/manual/reference/operator/query/in/

How can i do it using morphia ?

If i give Field criteria with field operator as in and value of type "java.util.regex.Pattern" then the equivalent query generated in $in:[$regex: 'given pattern'] which wont return expected results at all.

Expectation: $in :[ /pattern1 here/,/pattern2 here/] Actual using 'Pattern' object : $in : [$regex:/pattern1 here/,$regex:/pattern 2 here/]

like image 598
Manoj Chandramohan Avatar asked Feb 26 '15 09:02

Manoj Chandramohan


2 Answers

I'm not entirely sure what to make of your code examples, but here's a working Morphia code snippet:

Pattern regexp = Pattern.compile("^" + email + "$", Pattern.CASE_INSENSITIVE);
mongoDatastore.find(EmployeeEntity.class).filter("email", regexp).get();

Note that this is really slow. It can't use an index and will always require a full collection scan, so avoid it at all cost!

Update: I've added a specific code example. The $in is not required to search inside an array. Simply use /^I/ as you would in string:

> db.profile.find()
{
  "_id": ObjectId("54f3ac3fa63f282f56de64bd"),
  "tags": [
    "India",
    "Australia",
    "Indonesia"
  ]
}
{
  "_id": ObjectId("54f3ac4da63f282f56de64be"),
  "tags": [
    "Island",
    "Antigua"
  ]
}
{
  "_id": ObjectId("54f3ac5ca63f282f56de64bf"),
  "tags": [
    "Spain",
    "Mexico"
  ]
}
{
  "_id": ObjectId("54f3ac6da63f282f56de64c0"),
  "tags": [
    "Israel"
  ]
}
{
  "_id": ObjectId("54f3ad17a63f282f56de64c1"),
  "tags": [
    "Germany",
    "Indonesia"
  ]
}
{
  "_id": ObjectId("54f3ad56a63f282f56de64c2"),
  "tags": [
    "ireland"
  ]
}
> db.profile.find({ tags: /^I/ })
{
  "_id": ObjectId("54f3ac3fa63f282f56de64bd"),
  "tags": [
    "India",
    "Australia",
    "Indonesia"
  ]
}
{
  "_id": ObjectId("54f3ac4da63f282f56de64be"),
  "tags": [
    "Island",
    "Antigua"
  ]
}
{
  "_id": ObjectId("54f3ac6da63f282f56de64c0"),
  "tags": [
    "Israel"
  ]
}
{
  "_id": ObjectId("54f3ad17a63f282f56de64c1"),
  "tags": [
    "Germany",
    "Indonesia"
  ]
}

Note: The position in the array makes no difference, but the search is case sensitive. Use /^I/i if this is not desired or Pattern.CASE_INSENSITIVE in Java.

like image 147
xeraa Avatar answered Oct 24 '22 04:10

xeraa


Single RegEx Filter

use .filter(), .criteria(), or .field()

query.filter("email", Pattern.compile("reg.*exp"));
// or
query.criteria("email").contains("reg.*exp");
// or
query.field("email").contains("reg.*exp");

Morphia converts this into:

find({"email": { $regex: "reg.*exp" } })

Multiple RegEx Filters

query.or(
    query.criteria("email").contains("reg.*exp"),
    query.criteria("email").contains("reg.*exp.*2"),
    query.criteria("email").contains("reg.*exp.*3")
);

Morphia converts this into:

find({"$or" : [ 
            {"email": {"$regex": "reg.*exp"}},
            {"email": {"$regex": "reg.*exp.*2"}},
            {"email": {"$regex": "reg.*exp.*3"}}
        ]
    })

Unfortunately,

You cannot use $regex operator expressions inside an $in. MongoDB Manual 3.4

Otherwise, we could do:

Pattern[] patterns = new Pattern[] {
    Pattern.compile("reg.*exp"),
    Pattern.compile("reg.*exp.*2"),
    Pattern.compile("reg.*exp.*3"),
};
query.field().in(patterns);

hopefully, one day morphia will support that :)

like image 3
Ali Saeed Avatar answered Oct 24 '22 05:10

Ali Saeed