Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

php Mongo find only utilize 4 criteria

-->Please see updates at the bottom, I have replicated the same issue in Mongo shell

My criteria is being passed via GET parameters and gets placed into $data (as an assc array). Then it gets to below section, where each search term becomes partial not exact match. After that we remove (unset) empty criterias.

In total there are possible 15 fields which at least 1 and at most all 15 can be set.

foreach ($data as $k => $v) { 
     // Make them partial match
     $data[$k] = new MongoRegex('/'.$v.'/i');
     // Remove empty criteria
     if (empty($v)) unset($data[$k]); 
}
// Run the search
$cursor = $this->collection->find($data);

Everything works sweet as long as passed criterias are 4 or less like:

Array ( 
   [phone] => MongoRegex Object ( [regex] => 433 [flags] => i ) 
   [property_name] => MongoRegex Object ( [regex] => west [flags] => i ) 
   [city] => MongoRegex Object ( [regex] => H [flags] => i ) 
   [zip_postcode] => MongoRegex Object ( [regex] => 9 [flags] => i ) 
)

This returns 5 results.

But any criteria added after 4th one are ineffective.

Array ( 
   [phone] => MongoRegex Object ( [regex] => 433 [flags] => i ) 
   [state_province] => MongoRegex Object ( [regex] => Virginia [flags] => i ) 
   [property_name] => MongoRegex Object ( [regex] => west [flags] => i ) 
   [city] => MongoRegex Object ( [regex] => H [flags] => i ) 
   [zip_postcode] => MongoRegex Object ( [regex] => 9 [flags] => i )
)

This should return 2 but still returns 5 and it will return 5 no matter how many criteria items are added

-- Update --

So I have tried it in the Shell and to my surprise it also does not work there.

db.property_list.find({phone:/433/, property_name:/west/, city:/h/, zip_postcode:/9/}).count()

returns 5

Now when I add the 5th parameter it should narrow down the results to 2 but it is ineffective and still show count as 5!!!

db.property_list.find({phone:/433/, property_name:/west/, city:/h/, zip_postcode:/9/, state_province:/Virginia/}).count()

returns 5

With a lot of experiments, I realized it is only the first 4 criteria being picked up!! Like if in the last example I switch the place for 'state_province' and 'city' it will be 'city' criteria which will be ineffective as it will be the 5th criteria!!

-- New Update --

It turns out if I use normal match instead of regex on the 5th criteria it will work. Am I correct to assume Mongo can do find() only for 4 regex criteria? So this will correctly returns 1

db.property_list.find({phone:/433/, property_name:/west/, city:/h/, zip_postcode:/9/, state_province:Virginia}).count()
like image 505
Mazzi Avatar asked Nov 05 '22 00:11

Mazzi


1 Answers

There is a hard limit of 4 allowed regex criteria per query. It was fixed in the core mongo code about six months ago: https://github.com/mongodb/mongo/commit/62554d064a264f9b6c28099ba71421f250bbbba9

It looks like this fix has not been pulled into the 1.8 or 2.0 branches of mongo yet, here's the v1.8 branch showing the hard limit: https://github.com/mongodb/mongo/blob/v1.8/db/matcher.cpp#L159

like image 112
SteveK Avatar answered Nov 15 '22 05:11

SteveK