Оценка запросов, связанных с MongoDB-JSON, в PHP

Рассмотрим следующий (довольно сложный) запрос, выраженный в этом объекте JSON:

{ "name": "Kindle Fire", "sale": true, "price": { "$gt": 199, "$lt": 264 }, "price.vat": { // bogus, just to show $a['price.vat'] == $a['price']['vat'] "$lte": 1.2 }, "$or": { "qty": { "$gt": 30 }, "eta": { "$or": { "$lt": 3, "$gt": 30 } } }, "countriesAvailable": { "$in": [ "US", "CA" ] } } 

Задача


Я хочу проанализировать этот JSON так, чтобы он оценивал эквивалент PHP (где $a – мои целевые данные):

 $a['name'] == 'Kindle Fire' && $a['sale'] == true && ( $a['price'] > 199 && $a['price'] < 264 ) && $a['price']['vat'] <= 1.2 && ( $a['qty'] > 30 || ( $a['eta'] < 3 || $a['eta'] > 30 ) ) && in_array($a['countriesAvailable'], array('US', 'CA')) 

У меня мало опыта создания оценщиков выражений. Моя идея состоит в том, чтобы пройти запрос от самого внутреннего уровня до самого внешнего уровня, вызвав соответствующие методы оператора MongoDB по мере необходимости.

Предполагая, что $a соответствует запросу, это будет план оценки:

 $query = array(); $query['name'] = true; $query['sale'] = true; $query['price'] = array(); $query['price']['$gt'] = true; $query['price']['$lt'] = true; $query['price']['vat'] = array(); $query['price']['vat']['$lte'] = true; $query['$or'] = array(); $query['$or']['qty'] = array(); $query['$or']['qty']['$gt'] = false; $query['$or']['eta'] = array(); $query['$or']['eta']['$or'] = array(); $query['$or']['eta']['$or']['$lt'] = true; $query['$or']['eta']['$or']['$gt'] = false; $query['countriesAvailable'] = array(); $query['countriesAvailable']['$in'] = true; 

Второй шаг:

 $query = array(); $query['name'] = true; $query['sale'] = true; $query['price'] = array(); $query['price']['$gt'] = true; $query['price']['$lt'] = true; $query['price']['vat'] = true; $query['$or'] = array(); $query['$or']['qty'] false; $query['$or']['eta'] = array(); $query['$or']['eta']['$or'] true; $query['countriesAvailable'] = true; 

Третий шаг:

 $query = array(); $query['name'] = true; $query['sale'] = true; $query['price'] = true; $query['$or'] = array(); $query['$or']['qty'] false; $query['$or']['eta'] true; $query['countriesAvailable'] = true; 

Четвертый шаг:

 $query = array(); $query['name'] = true; $query['sale'] = true; $query['price'] = true; $query['$or'] = true; $query['countriesAvailable'] = true; 

Поскольку все значения являются логическими, оценка заканчивается возвратом !in_array(false, $query, true) .

Если есть лучший подход, дайте мне знать.

Проблема: доступ к родительским массивам


Я застреваю, пытаясь получить самые внутренние элементы и соответствующий (игнорирующий операторов) путь индекса массива, например, если я использую RecursiveIteratorIterator я получаю правильные значения для первой итерации:

 $nodes = new ArrayIterator($query); $iterator = new RecursiveArrayIterator($nodes); $iteratorIterator = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::LEAVES_ONLY); print_r(iterator_to_array($iteratorIterator)); Array ( [name] => Kindle Fire HD [sale] => 1 [$gt] => 30 [$lt] => 3 [$lte] => 1.2 [0] => US [1] => CA ) 

Тем не менее, это малопригодно, так как я не могу быть уверен в том, что $a индекс, на который ссылаются ключи, не говоря уже о том, что значения ключа переписываются последними записями и тот факт, что я не могу изменить их значения.

Я также пробовал играть с RecursiveArrayIterator , но без hasParent() / getParent() это, похоже, не дает мне много преимуществ перед простое вычисление массива.

Какие-либо предложения?

Solutions Collecting From Web of "Оценка запросов, связанных с MongoDB-JSON, в PHP"

Я быстро прочитал ваш вопрос, похоже, что вы хотите посетить листья и узнать ключ к ним.

так вот:

 $ritit = new RecursiveIteratorIterator(new RecursiveArrayIterator($myArray)); foreach ($ritit as $leafValue) { $keyPath = array(); foreach (range(0, $ritit->getDepth()) as $depth) { $keyPath[] = $ritit->getSubIterator($depth)->key(); } // do something with $keyPath // or $hasParent = $ritit->getDepth() > 0; $parentIter = $ritit->getSubIterator($ritit->getDepth() - 1); $parentKey = $parentIter->key(); }