Is there a way to do "include" or "in" the api? filter by array of ids

I have a list of computers that i get via the rest API /computers, then I’d like to get more info via relevance. I want to get all the data at once, or maybe use chunks.

This doesn’t work:
'(id of it, name of it, operating system of it) of bes computers whose ((id of it = (123, 3312)))'

I assume the alternative is using “OR” operator.
im trying something like :
'(id of it, name of it, operating system of it) of bes computers whose ((id of it = (123)) or (id of it = (12344)))'

Whats the best way to do this?

Thanks!

You could check whether the ID is in a ‘set’…

id of it is contained by set of (123; 1234)
1 Like

Thank you so much! This was it.
Here is the final query:

operating system  whose (name of it is contained by set of ("Linux Red Hat Enterprise Linux 8.1";"Windows"))

What are you trying to get here?

operating system is an object with many properties

You could have exists operating system whose (name of it is contained by set of ("Linux Red Hat Enterprise Linux 8.1";"Windows")) to see if the OS is one that you are insterested in.

You then just need to get the exact names of the OSs in question (hint, name of operating system on my Windows laptop does not evaluate to “Windows”)

I’ll try to give an example that is closer to what I’m looking for.

I want to fetch all computers, additional fields that are not returned in the /computers endpoint and their CVEs .

I run a few queries.

  1. First, fetch all the computers using rest /computers
  2. Then I fetch all computers that values values for each specific field
  3. Then I fetch all CVEs for each computer separately

I want to optimize it by combining some queries together. Instead of fetching CVEs for each computer.
I use the following query to fetch the CVE (i didn’t put all the fields here for readability )

(name of it, cve id list of it, name of site of it, source severity of it, source release date of it) of relevant fixlets whose ((category of it contains (case insensitive regex "Security\sAdvisory|Security\sHotfix| Security\sUpdate|Service\sPack")) .... of bes computers whose (id of it = {computer_id})

instead, I want to add at the end

… of bes computers whose (id of it is contained by set of (id1;id2;id3))

Currently, since we are making a lot of requests - for each computer, it is running slow. I’d like to batch these somehow.

The issue that I currently encounter is that when i add multiple IDs, i can’t tell which computer it belongs to. i want to group CVEs by computers.

Thanks for the help here! highly appreciated.

I did find that relevant fixlets contain “applicable computer of” but when I try to add it

(name of it, cve id list of it, applicable computer of it) of relevant fixlets

but I’m getting an error

The operator "string" is not defined
applicable computer of is type of bes computer, not sure how to pull this info. other fields like name of it, cve id list of it returning strings

I’m afraid I can’t dedicate a long post on this tonight, but should be able to revisit tomorrow.
edit: I guess I did have time for a long post

The main issue we usually see with query efficiency is the “looping” effect that comes from creating a cross-product. When you take an operation like

(relevant fixlets of it) of bes computers whose (some condition)

What actually happens, is that for each computer, the query for ‘relevant fixlets’ is repeated, along with whatever filters you are applying for that fixlet selection.

If you have ten computers, the ‘relevant fixlets’ query is repeated ten times. A thousand computers? A thousand times through the ‘relevant fixlets’ loop.

The most authoritative guide on this behavior, and how to optimize, is in @brolly33’s post at Efficient Session Relevance Query for Computer Properties

The primary tactic there is for computer property lookups, but can be applied to Fixlet/Computer couplings as well. The approach is to first build a filter for computers, and combine those computers into a ‘set’. Since a ‘computer set’ is actually a single object, that prevents repeating the ‘property’ or ‘fixlet’ lookup and filtering. Perform the Fixlet filtering (creating a ‘bes fixlet set’), and then after performing all the fixlet and computer lookups, unwind the two sets and match the results against each other.

The base form could start with something like

(
   set of bes fixlets whose (exists applicable computers of it and category of it contains (case insensitive regex "Security\sAdvisory|Security\sHotfix| Security\sUpdate|Service\sPack"

, set of bes computers whose (id of it is contained by set of (123;456;789)     
) 

By creating the ‘sets’, the computer lookups are performed only once (not repeated for every fixlet), and the fixlet lookups are also performed only once (not repeated for every computer)

From there, you can unwind the sets and only keep the results where a fixlet member is relevant on the computer member…

(elements of item 0 of it, elements of item 1 of it) 
   whose (relevant flag of result (item 0 of it, item 1 of it) of
(
   set of bes fixlets whose (exists applicable computers of it and category of it contains (case insensitive regex "Security\sAdvisory|Security\sHotfix| Security\sUpdate|Service\sPack"

, set of bes computers whose (id of it is contained by set of (123;456;789)     
) 

I’m not connected to my lab right now but I think that should give you a result where ‘item 0’ is the relevant fixlet and ‘item 1’ is the applicable computer for that fixlet. From there you can lookup Fixlet properties from item 0 and Computer properties from item 1. Something like

(
name of item 0 of it /* Fixlet Name */
, cve id list of item 0 of it /* Fixlet CVE ID List */
, name of site of item 0 of it /* Fixlet Site */
, source severity of item 0 of it /* Fixlet Severity */
, source release date of item 0 of it /* Fixlet Release Date */
, id of item 1 of it /* Computer ID */
, name of item 1 of it | "Computername Not Reported" /* ComputerName or message */
, last report time of item 1 of it /* Computer Last Reported */
) of 
(elements of item 0 of it, elements of item 1 of it) 
       whose (relevant flag of result (item 0 of it, item 1 of it) of
    (
       set of bes fixlets whose (
         exists applicable computers of it
         and exists cve id list of it
         and category of it contains 
              (case insensitive regex "Security\sAdvisory|Security\sHotfix| Security\sUpdate|Service\sPack")
         )

    , set of bes computers whose (id of it is contained by set of (123;456;789)     
    ) 

Let me know if this helps. If there’s a bug in here I should be able to check it out in my lab tomorrow. For performance, the more filtering you can do on the computers or fixlets up-front, the better - especially if you can limit the sites for the fixlets of interest so that we don’t scan every fixlet site.

1 Like

Thank you for this detailed response! I believe I understand the gist of the structure: I need to create sets and then pick from these sets.
Im struggling with the sets syntax.
I tried a simple one like:

set of bes computers whose (id of it = 123)

I keep getting The operator “string” is not defined
how can I try out each building block before I create the entire query? what am i missing in the set syntax?

That’s because ‘set’ cannot be interpreted directly as a string…you can either print something like size of set of BES computers whose() or inspect the elements of the set like number of elements of set of BES computers whose() or names of elements of set of BES computers whose()

@JasonWalker thank you for all the help. I did a few changes in various queries that I was doing and improved the performance significantly. I still have a few open ends and might get back to this query. I’ll reach out of I struggle with it.

Thank you again!

1 Like