ohler55/ojg

Parsing a filter expression using Equation

juliannguyen4 opened this issue · 14 comments

I'm trying to parse the JSONPath $[?(@.price < 10)] in code by passing it to:

expr := jp.MustParseString("$[?(@.price < 10)]")

and reading each fragment in expr. But I'm unable to parse the filter expression in the path.

I know that filter expressions are first declared as Equation objects in code and passed into Filter objects, and the Filter objects encode these Equation objects in an internal data structure. But so far, I haven't found a way to convert the Filter objects back to Equation objects. Is there a way to do this?

I see the confusion, Equation instances are used to build a Script if building by hand. After setting up an Equation the Script() function is called to return a Script or Filter() is called to return a Filter. You can't go the other way around from Filter to Equation. The end goal is to produce a Filter or Script and Equation is just one of the ways to do that.

Hi @ohler55, would it be possible to make an Equation accessible from a Filter?

In my code I'm iterating through each Frag in the Expr and I would like to add support for filter expressions, and the Frag type that contains a filter expression is *Filter. But I'm unable to access the filter expression (via Equation) programmatically through a Filter object.

I'm also willing to make a PR to support this, if you're OK with that.

I'm not sure using the Equation type is the best way to view the Filter internals. Can you provide a bit more on what it is you are trying to do the the Filter? Let's see if we can come up with something.

Hi @ohler55 , sorry for the late reply. I'll try my best to explain.

I'm currently developing an API that converts JSONPath strings into Aerospike server operations, and I'm doing this for Aerospike's Golang client. The way the API currently works is:

  1. It takes in JSONPath strings through an API call
  2. It parses the JSONPath string using the jp library into an Expr object
expr, err := jp.ParseString(jsonPath)
  1. Then, one by one, it reads each Frag in the expr (which is basically a list of Frag objects). It determines which kind of operation it is and translates it to a server operation. For example, if the frag has a concrete jp.Nth type, we would translate that to a server operation that gets a list item at a specific index.

The problem is that filter expressions are encoded as Filter objects (which is also a Frag), but there's no way to access the expression itself for a Filter object. If there's a way to access the Equation of a filter such as this, we would easily be able to convert it to the equivalent server operation.

I see. Right now you can get the string representation of the filter but then you would have to parse the string which would be a pity since the filter already has the info. Let's look at what would be the ideal solution first then see what can reasonably be done.

If a call was added to Filter and Script (might as well) that returned some kind of struct or slice of structs that described the Script/Filter I think that would be best for your situation. The struct should include the left side, right side, and operation. Something like:

type Foo struct {
    op   string
    left any
    right any
}

What do you think?

That looks good for binary operations. For unary operations like getting an item from a map (i.e @.key), we can set the right attribute to be nil.

Exactly. That's what OjG does.

I started a branch named "inspect-filters". I'll be working in that branch to add this feature.

I have an implementation but I need more tests. Please give it a try.

Testing complete but could use some feedback about whether it works for you.

Hi @ohler55 , thank you so much for getting back to me. I'll check if my code works with yours

Please let me know if the addition works for you.

Hi @ohler55, I have to put my project on the backlog for a few weeks, but I will continue working on this at the start of next month. Thanks for helping me out by adding this feature!!

Ok, I'll merge and release anyway.

v1.15.0 released