考虑在此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 operator方法。
假设$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()
方法,它似乎没有给我带来太多的优势,只是简单地预测数组。< / p>
有什么建议吗?
答案 0 :(得分:3)
我很快就读到了你的问题,听起来你想要访问叶子并知道它们的关键路径。
所以这里:
$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();
}