Community discussions

MikroTik App
 
User avatar
DenSyo77
just joined
Topic Author
Posts: 24
Joined: Tue Jan 09, 2024 10:38 am
Contact:

How using .query stack in REST API?

Fri Feb 02, 2024 4:11 am

How to work with query stack in REST API?
For example, print address lists with condition:
/ip firewall address-list print where (list=a or list=b or list=c) and address=d
in REST API like this POST request /rest/ip/firewall/address-list/print
{".query": ["list=a","list=b","#|","list=c","#|","address=d","#&"]}

How to create a condition with brackets like this expression?
/ip firewall address-list print where (list=a or list=b or list=c) and (address=d or comment=d)
The documentation says that can access the query stack using indexes, but I don’t understand how it works.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3605
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: How using .query stack in REST API?

Fri Feb 02, 2024 4:48 am

I have an example here: viewtopic.php?t=198974#p1021503
e.g.
USER=admin ROUTER=192.168.88.1; curl -l -u $USER -X POST http://$ROUTER/rest/ip/firewall/nat/print -H "Content-Type: application/json" --data '{".query": ["chain=dstnat","chain=srcnat","#|!"]}' 
It's tricky with .query in JSON. The comparison operators are all "stack based" (like an old HP RPN calculator). But AFAIK all operators should be at end of the array, working down the stack.

How .query work is semi-described in API docs as it follows Mikrotik older/non-HTTP API: https://help.mikrotik.com/docs/display/ ... PI-Queries – but seems you figured out that part.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3605
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: How using .query stack in REST API?

Fri Feb 02, 2024 5:19 am

I tried your version and it works for me...

and this version of .query also worked:
USER=admin ROUTER=192.168.88.1; curl -l -u $USER -X POST http://$ROUTER/rest/ip/firewall/address-list/print -H "Content-Type: application/json" --data '{".query": ["list=a","list=b","list=c","#|","#|","address=159.148.147.252","#&"]}' -- | jq '.'
[
  {
    ".id": "*A1E70",
    "address": "159.148.147.252",
    "comment": "ftp.mikrotik.com",
    "creation-time": "2024-02-01 19:11:41",
    "disabled": "false",
    "dynamic": "true",
    "list": "a"
  },
  {
    ".id": "*A1E71",
    "address": "159.148.147.252",
    "comment": "ftp.mikrotik.com",
    "creation-time": "2024-02-01 19:11:51",
    "disabled": "false",
    "dynamic": "true",
    "list": "b"
  },
  {
    ".id": "*A1E72",
    "address": "159.148.147.252",
    "comment": "ftp.mikrotik.com",
    "creation-time": "2024-02-01 19:12:12",
    "disabled": "false",
    "dynamic": "true",
    "list": "c"
  }
]
using this test data:
/ip firewall address-list
add address=ftp.mikrotik.com list=a
add address=ftp.mikrotik.com list=b
add address=ftp.mikrotik.com list=c
add address=cloud.mikrotik.com list=c
add address=cloud2.mikrotik.com list=c
add address=ftp.mikrotik.com list=e

with ftp.mikrotik.com resolve to 159.148.147.252
 
User avatar
DenSyo77
just joined
Topic Author
Posts: 24
Joined: Tue Jan 09, 2024 10:38 am
Contact:

Re: How using .query stack in REST API?

Fri Feb 02, 2024 5:30 am

This query expression: {".query": ["list=a","list=b","#|","list=c","#|","address=d","#&"]} is works, yes, and I using your example for write this.
I'm interested in how to construct an expression similar to this: where (list=a or list=b or list=c) and (address=d or comment=d)

The documentation talks about indexes of expressions sent to the stack, and if try to use constructs like: "#0|3" or "#0&4", can see that this has an impact on the query result, but there is absolutely no understanding of how to use it correctly.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3605
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: How using .query stack in REST API?

Fri Feb 02, 2024 5:52 am

LOL. I read what you wrote but cut-and-pasted the wrong one.

I think this should work:
["list=a","list=b","list=c","#|","#|","address=159.148.147.252","comment=rem", "#|", "#&"]

adding this to above...
/ip/firewall/address-list/add address=www.mikrotik.com comment=rem list=a

"#....." op resolves two items in the stack into one, BUT the one result remains on the stack... e.g. removes the two item, but pushes true/false to stack.

Maybe if you visual like this since when the #| or #& operators resolves...
["list=a","list=b","list=c","#|","#|","address=159.148.147.252","comment=rem", "#|", "#&"]
["list=a",true,"#|","address=159.148.147.252","comment=rem", "#|", "#&"]
[true,"address=159.148.147.252","comment=rem", "#|", "#&"]
[true,true, "#&"]
[true]
Last edited by Amm0 on Fri Feb 02, 2024 5:54 am, edited 1 time in total.
 
User avatar
DenSyo77
just joined
Topic Author
Posts: 24
Joined: Tue Jan 09, 2024 10:38 am
Contact:

Re: How using .query stack in REST API?

Fri Feb 02, 2024 5:53 am

Yes! I'm still testing it, but it's already working:
{".query": ["list=a","list=b","#|","list=c","#|","comment=d","address=d","#|","#&"]}
equal to: (list=a or list=b or list=c) and (address=d or comment=d)

The great force of brute force is at work, but trying to use the numbers was unnecessary...

Thanks, Amm0! 10 minutes passed and the stack processing logic finally became clear to me :)
Last edited by DenSyo77 on Fri Feb 02, 2024 6:05 am, edited 1 time in total.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3605
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: How using .query stack in REST API?

Fri Feb 02, 2024 6:03 am

I did use an HP calculator for years.

I kinda use "jq" in shell scripts or map()/reduce() in JavaScript to avoid dealing with the .query – although it more efficient to use .query to avoid unneeded data transfer.
Last edited by Amm0 on Fri Feb 02, 2024 6:11 am, edited 1 time in total.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3605
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: How using .query stack in REST API?

Fri Feb 02, 2024 6:08 am

FWIW, I'm pretty sure the last "#&" is unnecessary since default is AND. And in the example above, the stack have [true, true] on a match.
 
User avatar
DenSyo77
just joined
Topic Author
Posts: 24
Joined: Tue Jan 09, 2024 10:38 am
Contact:

Re: How using .query stack in REST API?

Fri Feb 02, 2024 6:13 am

Yes, works without last and
{".query": ["list=a","list=b","#|","list=c","#|","comment=d","address=d","#|"]}
{".query": ["list=a","list=b","list=c","#|","#|","comment=d","address=d","#|"]}
 
User avatar
DenSyo77
just joined
Topic Author
Posts: 24
Joined: Tue Jan 09, 2024 10:38 am
Contact:

Re: How using .query stack in REST API?

Fri Feb 02, 2024 7:07 am

Since already dealt with the query, did it as needed.
{".query": ["disabled=false","list=a","list=b","#|","list=c","#|","comment=d","address=d","#|","timeout","#!","dynamic=true","#&!"]}
is equal to: where !disabled and (list=a or list=b or list=c) and (address=d or comment=d) and !(!timeout and dynamic)
- thus, dynamic addresses created by the system based on domain names are ignored.

Will make an explanation to make it easier for everyone interested to understand. And is applied by default to all expression results not explicit used on operation in stack:
{".query": ["disabled=false" AND "list=a","list=b","#|","list=c","#|" AND "comment=d","address=d","#|" AND "timeout","#!","dynamic=true","#&!"]}
 
User avatar
DenSyo77
just joined
Topic Author
Posts: 24
Joined: Tue Jan 09, 2024 10:38 am
Contact:

Re: How using .query stack in REST API?

Fri Feb 02, 2024 2:41 pm

Indexes can be used in an expression, but the logic is not always clear and there are no advantages over a regular chain, except perhaps to do obfuscation.
{".query": ["disabled=true","list=a","list=b","list=c","#|","#|","comment=d","address=d","#|","timeout","#!","dynamic=true","#&!","#2&1&0"]}
- in this example the expression "disabled=true" is ignored, "timeout","#!" - timeout is nothing, "#2&1&0" - changing the index order gives a different result, it looks like this is the "left to right" that documentation says.
Last edited by DenSyo77 on Sat Feb 03, 2024 4:11 am, edited 1 time in total.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3605
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: How using .query stack in REST API?

Fri Feb 02, 2024 4:14 pm

, except perhaps to do obfuscation.
{".query": [...,"#&!","#2&1&0"]}
Well...there we're no example of using the "stack index" operators AKAIK. Bravo!

Do think "#|" and "#&" – in right spots – is likely what most folks need to know about .query in REST*. And even those two ops, with the stack, is pretty far from a "print where". e.g. if you're trying to "port" a CLI into a REST request.

* And perhaps using =true or =false for boolean config items like disable= etc — which you show here too.
 
User avatar
DenSyo77
just joined
Topic Author
Posts: 24
Joined: Tue Jan 09, 2024 10:38 am
Contact:

Re: How using .query stack in REST API?

Sat Feb 03, 2024 1:25 am

Amm0, title of the post has taken on a different meaning, now this is an expanded version of your previous instructions.

Block that uses indexes pushes the result to the top of stack, clearing the entire stack - all expressions unused before this step will be lost. Operations & and | can be applied to indexes, but it is difficult to understand the priority and logic of the actions performed. The only thing that is clear is that if something goes wrong, the expression is written with an error, then the system will return either all addresses from the firewall lists (accessing a non-existent index), or result of the last index in expression (syntax or procedure error).
"#." creates a copy of the top of stack - this is an interesting feature that can be used to construct complex expressions.

For some reason, I have never encountered such an approach with a stack to organizing logical calculations before. Really liked its simplicity of implementation, will use it in my projects when need to be able to set the behavior of an object by user in settings.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3605
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: How using .query stack in REST API?

Sat Feb 03, 2024 4:23 am

For some reason, I have never encountered such an approach with a stack to organizing logical calculations before. Really liked its simplicity of implementation, will use it in my projects when need to be able to set the behavior of an object by user in settings.
I like esoteric programming languages. RouterOS script is in that category. Someone at Mikrotik must have read Ken Iverson books (creator of array languages like APL, J) & be an expert at lex/yacc is all I know. But if you like ".query stack", you'd like https://www.uiua.org - dozen of primitives to operate on a stack expressed as unicode symbols.
 
User avatar
DenSyo77
just joined
Topic Author
Posts: 24
Joined: Tue Jan 09, 2024 10:38 am
Contact:

Re: How using .query stack in REST API?

Sat Feb 03, 2024 4:52 am

Thank you very much, Amm0! Very interesting ideas that may be useful to me.

Who is online

Users browsing this forum: Google [Bot] and 12 guests