TomFrost / Jexl

Javascript Expression Language: Powerful context-based expression parser and evaluator
MIT License
561 stars 92 forks source link

How can I use a unary operator? #66

Closed Melodyn closed 4 years ago

Melodyn commented 4 years ago

I did not find examples of its use in the readme. Is it possible to build "not in" conditions?

const context = {
  peoples: [
    { first: 'Lana', last: 'Kane', hobby: ['guitar', 'flowers'] },
    { first: 'Cyril', last: 'Figgis', hobby: ['computer', 'cats'] },
    { first: 'Pam', last: 'Poovey', hobby: ['poetry', 'dogs'] }
  ]
}

jexl.eval('!(peoples["dogs" in .hobby])', context);
/* result:
{ first: 'Lana', last: 'Kane', hobby: ['guitar', 'flowers'] },
{ first: 'Cyril', last: 'Figgis', hobby: ['computer', 'cats'] },
*/
TomFrost commented 4 years ago

Hi Melodyn!

It looks like you’re negating a collection of objects with your !, rather than the filter criterion. Try this instead:

jexl.eval('peoples[!("dogs" in .hobby)]')

I apologize, normally I’d try this myself before posting, but I’m mobile for the next few hours. Happy to dig in further if that doesn’t work though!

TomFrost commented 4 years ago

Ok, I got a moment to test this and my solution above definitely does not work. It would appear that filtering an array by using an in condition (even without the unary operator) fails, and I'm guessing it has to do with how jexl detects the use of relative identifiers.

The good news is, there's a very easy workaround for this. Just add this to your code when you initialize Jexl:

jexl.addTransform('contains', (ary, search) => ary.includes(search))

And now you can filter with no problem:

jexl.evalSync('peoples[!.hobby|contains("dogs")]', context)

Output:

[
  { first: 'Lana', last: 'Kane', hobby: [ 'guitar', 'flowers' ] },
  { first: 'Cyril', last: 'Figgis', hobby: [ 'computer', 'cats' ] }
]

Let me know if that solves your immediate need, and I'll start looking into the in issue!

Melodyn commented 4 years ago

Hi Tom!

Yes, this solution suits me. Thank you for your prompt reply and your wonderful library :)