Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combine and/or to create more complex models #15

Open
FlorianRuen opened this issue Jul 20, 2023 · 5 comments
Open

Combine and/or to create more complex models #15

FlorianRuen opened this issue Jul 20, 2023 · 5 comments

Comments

@FlorianRuen
Copy link

Hey,

I am currently working on a project, in which I am trying to build rules models (a bit like rules for a firewall) and I did not find, in the docs, an answer to some of my questions :

  • Is it possible to combine or / and ? For example to make a rule which would be: the variable (a > 0 and b < 4) OR (b == 5 and a < 10) with multiples rules (here just two, but we can imagine more OR here)

  • Do you use any standard that can be parsed in another language ? For example, generate the json using JS/react, but apply rules with data/schema in Golang ?

  • Do you known if there is a compact and good UI generator to output this kind of schema (if the schema match some standards) or do I need to recreate something my myself ?

Hope you can help me to choose the right library !

@TotalTechGeek
Copy link
Owner

Hey @FlorianRuen,

it possible to combine or / and ? For example to make a rule which would be: the variable (a > 0 and b < 4) OR (b == 5 and a < 10) with multiples rules (here just two, but we can imagine more OR here)

Absolutely! It might be helpful to think of JSON-Logic as a dialect of Lisp. That specific rule would be:

{
        or: [
          {
            and: [
              {
                '>': [
                  {
                    var: 'a'
                  },
                  0
                ]
              },
              {
                '<': [
                  {
                    var: 'b'
                  },
                  4
                ]
              }
            ]
          },
          {
            and: [
              {
                '==': [
                  {
                    var: 'b'
                  },
                  5
                ]
              },
              {
                '<': [
                  {
                    var: 'a'
                  },
                  10
                ]
              }
            ]
          }
        ]
}

Additionally, and and or take in a variable number of arguments. So you wouldn't need to do

(and (> a 5) (and (< a 10) (== a 7))), you could do (and (> a 5) (< a 10) (== a 7))

Do you use any standard that can be parsed in another language ? For example, generate the json using JS/react, but apply rules with data/schema in Golang ?

The "standard" we use is JSON-Logic, and there's an ecosystem of other libraries that use it. https://jsonlogic.com/

This project is an alternative implementation of the mainline javascript project, to add support for asynchronous methods and performance optimizations via compilation.

Do you known if there is a compact and good UI generator to output this kind of schema (if the schema match some standards) or do I need to recreate something my myself ?

There are some projects listed on npm that provide native support for JSON Logic, but any rules builder UI should work (this should broaden the options available to your project). It's usually pretty simple to map from one rules dialect to another. If you need assistance with this, I'd be happy to help.

@FlorianRuen
Copy link
Author

FlorianRuen commented Jul 21, 2023

Great @TotalTechGeek, seems a very good implementation!

Just two more questions :

  • There is any limitation on types that works ? For example if I want to use BigInt (a > BigInt value)
  • In addition to the result true / false, is it possible to get the reason (for example false because a not equals to 0 as error message or something), because I need the reason why the data not matched (user friendly) or do I need to parse myself ?

For the builder, I didn't really found a good library that can handle a form (with + to add rule)
But, maybe I can create the form builder myself (maybe in opensource related to this json logic), using something like https://github.com/krismuniz/js-to-json-logic, to convert string to json logic

I will do some tests using sample data on many json logic, but seems a good way to create what I need!

@TotalTechGeek
Copy link
Owner

There is any limitation on types that works ? For example if I want to use BigInt (a > BigInt value)

Ah! Good callout!

BigInt will work with all of the comparison operators, but will not work with the arithmetic expressions.

For your use-case, it sounds like you're mainly interested in the comparisons & boolean logic, so it shouldn't impact you, but I'm going to try to resolve that in the next day or so.

While most types (and things like Maps & Sets) pass into the logic just fine, I actually did forget to consider BigInt in my test cases.

In addition to the result true / false, is it possible to get the reason (for example false because a not equals to 0 as error message or something), because I need the reason why the data not matched (user friendly) or do I need to parse myself

You could, but not by default out of the box. Importing an extension would be necessary.

As JSON Logic is more like a sandboxed Lisp dialect, it's better to think of this library as a performant expression evaluator.

If this functionality is necessary, while I could recommend "Hey, try importing these methods into the engine", the same extensions would need to be ported over to the other libraries (like in Golang), so that likely wouldn't be ideal.

So instead of changing the expressions, one option that is portable is to generate expressions that will return an error:

const detectErrors = engine.build({
  if: [
    { '<': [{ var: 'a' }, 5] },
    'a is less than 10',
    { '>': [{ var: 'a' }, 10] },
    'a is greater than 10',
    null
  ]
}) 

if (detectErrors({ a: 3 })) {
  // ... 
}

@FlorianRuen
Copy link
Author

FlorianRuen commented Jul 25, 2023

@TotalTechGeek thank you for your great advices !

If you need some example for BigInt, feel free to ask. At the moment, I don't think I will create some arithmeric operations using BigInt (but I will try to think if this use case can be helpful)

Regarding error detection, for the moment I will put it aside, because it somewhat complicates the operation (especially with a UI generator). But it's good to know that it is possible !

For the UI, I will use https://github.com/ukrbublik/react-awesome-query-builder
But it seems, artihmeric operators like plus, minus, multiply and divide isn't supported by default (but maybe I can achieve using custom operators)

Do you have already used this UI library ? Any advice regarding arithmeric operators ?

@Mihailoff
Copy link
Contributor

Mihailoff commented Sep 27, 2023

In addition to the result true / false, is it possible to get the reason (for example false because a not equals to 0 as error message or something), because I need the reason why the data not matched (user friendly) or do I need to parse myself

How about something like this?

{ and: [
  { log: 'a should be lees than b' },
  { '<': [{ var: 'a' }, { var: 'b' }] },
  { log: 'b should be lees than c' },
  { '<': [{ var: 'b' }, { var: 'c' }] },
  { log: null }
] }

The latest log message will explain where it stopped. I haven't tested this, just an idea. Writing a message can be impractical, maybe the engine could return/store the index/location of the latest evaluated rule before exiting!?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants