草庐IT

php - 在 PHP 中评估类似 MongoDB 的 JSON 查询

coder 2024-01-01 原文

考虑在此 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;

由于所有值都是 bool 值,因此评估结束返回 !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 索引,更不用说键值正在被后面的条目覆盖,而且我可以'改变他们的值(value)观。

我也试过玩 RecursiveArrayIterator ,但如果没有 hasParent()/getParent() 方法,它似乎并没有给我比简单地 foreach 数组更多的优势。

有什么建议吗?

最佳答案

我很快读到了你的问题,听起来你想访问叶子并知道通往它们的关键路径。

所以在这里:

$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();
}

关于php - 在 PHP 中评估类似 MongoDB 的 JSON 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14070460/

有关php - 在 PHP 中评估类似 MongoDB 的 JSON 查询的更多相关文章

  1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  2. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  3. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  4. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

    我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

  5. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  6. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

  7. ruby - Ruby 是否有类似于 Perl 的 "perl -d"的逐步调试器? - 2

    Ruby是否有逐步调试器,类似于Perl的“perl-d”? 最佳答案 ruby-debug(对于ruby1.8),debugger(对于ruby1.9),byebug(对于ruby​​2.0)以及trepanning系列都有一个-x或--trace选项。在调试器内部,命令setlinetrace将打开或关闭线路跟踪。这是themanualforruby-debug原来的答案已经修改,因为数据噪声文章的链接,唉,不再有效了。还添加了ruby​​-debug的后继者 关于ruby-Ruby

  8. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

    假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

  9. 语法类似于 GitHub Flavored Markdown 的 Ruby markdown 解释器? - 2

    我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong

  10. ruby-on-rails - solr 清理查询 - 2

    我在Rails上使用带有ruby​​的solr。一切正常,我只需要知道是否有任何现有代码来清理用户输入,比如以?开头的查询。或* 最佳答案 我不知道执行此操作的任何代码,但理论上可以通过查看parsingcodeinLucene来完成并搜索thrownewParseException(只有16个匹配!)。在实践中,我认为您最好只捕获代码中的任何solr异常并显示“无效查询”消息或类似信息。编辑:这里有几个“sanitizer”:http://pivotallabs.com/users/zach/blog/articles/937-s

随机推荐