Relevance to cross-reference data from multiple WMI classes

Hello,

I just wanted to check if someone has come a better way to do cross-mapping of data from multiple WMI Classes? I have been using the following design on some occasions and it does work when it is 1-2-3 classes but I have an use case where I need to do 4 and that just goes off and never completes (with 3 classes it takes about 100 seconds which is bad enough but at least completes)…

Queries to retrieve data from 1st WMI Class:

((if exists string value of properties "Field1" of it then string value of properties ("Field1") of it else "<none>"), (if exists string value of properties "Field2" of it then (it as integer) of string value of properties ("Field2") of it else 0), (if exists string value of properties "Field3" of it then (it as integer) of string value of properties ("Field3") of it else 0)) of (select objects ("Field1,Field2,Field3 from SomeClass") of WMI)

Queries to retrieve data from 2nd WMI Class:

((if exists string value of properties "Field1" of it then string value of properties ("Field1") of it else "<none>"), (if exists string value of properties "Field2" of it then (it as integer) of string value of properties ("Field2") of it else 0), (if exists string value of properties "Field3" of it then (it as integer) of string value of properties ("Field3") of it else 0)) of (select objects ("Field1,Field2,Field3 from SomeClass2") of WMI)

Basic structure of the above into one and adding the cross-mapping from the data:

(item a of item 0 of it & " - " & item b of item 1 of it) of (1st Query, 2nd Query) whose (item x of item 0 of it = item y of item 1 of it)

I would have thought that based on the structure it just evaluates each of the queries once and then just uses the tuple result for the mapping/displaying but based on actual runtimes, it seems to be nesting the executions of each and essentially it is resulting in exponentially growing runtimes which at WMI class 4 are just no longer manageable. Question is whether there is a better way to structure it?

The pro-trick here is to turn the WMI queries into string sets and expand them upstream for the whose. Add additional sets at bottom as needed, and you only pay once for each set.

(item 0 of it & "-" & item 1 of it) 
OF
(elements of item 0 of it, elements of item 1 of it)   
          WHOSE (piece of item 0 of it= piece of item 1 of it)
OF
(set of (big WMI query) ,  set of (second big WMI query))

I am teaching a very similar topic at the next BigFix Masterclass in Colorado in October.

4 Likes

I maybe am missing something but isn’t string set one-dimensional object? What I need is to use one of the dimension from each query as key to map the data but then actually display the additional fields once data is mapped (don’t really care particularly about the Key field itself). I didn’t want to go with the actual technical details of my use case because code gets ugly/long/hard-to-follow in a hurry, so let’s stick with the generic example.

Assume that the first big wmi query returns 3 rows with 3 fields in each row:
CustomerID, CustomerName, Location
1, John, New York
2, Jane, Philadelphia
3, Jose, Miami

and the second big wmi query is again 4 by 3:
OrderID, CustomerID, TotalCost
1, 1, 10
2, 1, 15
3, 2, 12
4, 3, 20

I can convert each column in each result set to string set (and map the CustomerIDs from both) but that gives me access only to that column, essentially what I am after is the other columns and a result along the lines:

OrderID, CustomerName, Location, TotalCost
1, John, New York, 10
2, John, New York, 15
3, Jane, Philadelphia, 12
4, Jose, Miami, 20

And keep expanding, maybe pull some Order attribute from another WMI class based on the OrderID and so on… What I am after is to somehow mimic multidimensional string set but not even sure that will work because by nature (if not mistaken) string sets are unordered lists, where in my situation order does matter because the different classes is not going to have the data in the same order and I need an ordered multidimensional string set.

Build the sets at the bottom (because tuples create a cross product and 3x4 = 12 but 1x1 = 1)


q: number of ((1, "John", "New York"; 2, "Jane", "Philadelphia"; 3, "Jose", "Miami"),(1, 1, 10;2, 1, 15;3, 2, 12;4, 3, 20))
A: 12
T: 0.873 ms
I: singular integer


q: number of ((set of (it as string) of (1, "John", "New York"; 2, "Jane", "Philadelphia"; 3, "Jose", "Miami")),(set of (it as string) of (1, 1, 10;2, 1, 15;3, 2, 12;4, 3, 20)))
A: 1
T: 0.836 ms
I: singular integer

q: (elements of item 0 of it, elements of item 1 of it) of ((set of (it as string) of (1, "John", "New York"; 2, "Jane", "Philadelphia"; 3, "Jose", "Miami")),(set of (it as string) of (1, 1, 10;2, 1, 15;3, 2, 12;4, 3, 20)))
A: ( 1, John, New York ), ( 1, 1, 10 )
A: ( 1, John, New York ), ( 2, 1, 15 )
A: ( 1, John, New York ), ( 3, 2, 12 )
A: ( 1, John, New York ), ( 4, 3, 20 )
A: ( 2, Jane, Philadelphia ), ( 1, 1, 10 )
A: ( 2, Jane, Philadelphia ), ( 2, 1, 15 )
A: ( 2, Jane, Philadelphia ), ( 3, 2, 12 )
A: ( 2, Jane, Philadelphia ), ( 4, 3, 20 )
A: ( 3, Jose, Miami ), ( 1, 1, 10 )
A: ( 3, Jose, Miami ), ( 2, 1, 15 )
A: ( 3, Jose, Miami ), ( 3, 2, 12 )
A: ( 3, Jose, Miami ), ( 4, 3, 20 )
T: 0.615 ms
I: plural ( string, string )


Then whose on the expanded “Elements” since you already paid for the set up front, it is now a cheap operation

q: (elements of item 0 of it, elements of item 1 of it) whose (tuple string item 0 of item 0 of it = tuple string item 1 of item 1 of it) of ((set of (it as string) of (1, "John", "New York"; 2, "Jane", "Philadelphia"; 3, "Jose", "Miami")),(set of (it as string) of (1, 1, 10;2, 1, 15;3, 2, 12;4, 3, 20)))
A: ( 1, John, New York ), ( 1, 1, 10 )
A: ( 1, John, New York ), ( 2, 1, 15 )
A: ( 2, Jane, Philadelphia ), ( 3, 2, 12 )
A: ( 3, Jose, Miami ), ( 4, 3, 20 )
T: 0.402 ms
I: plural ( string, string )

Then pull the details of the string set out with Tuple String Items.

q: (tuple string item 0 of item 0 of it, tuple string item 1 of item 0 of it, tuple string item 2 of item 0 of it, tuple string item 2 of item 1 of it) of (elements of item 0 of it, elements of item 1 of it) whose (tuple string item 0 of item 0 of it = tuple string item 1 of item 1 of it) of ((set of (it as string) of (1, "John", "New York"; 2, "Jane", "Philadelphia"; 3, "Jose", "Miami")),(set of (it as string) of (1, 1, 10;2, 1, 15;3, 2, 12;4, 3, 20)))
A: 1, John, New York, 10
A: 1, John, New York, 15
A: 2, Jane, Philadelphia, 12
A: 3, Jose, Miami, 20
T: 0.224 ms
I: plural ( string, string, string, string )
1 Like

You did mention that order matters, and the Set of strings is going to alpha sort on that first field - in the example that works out, but if you have an example where it does not, we may need to use a concatenation instead of a Set to hold the base results from the Tuple in the Bottom.

That’s the bit I was missing, brilliant! Just FYI, the query as I had it with 4 WMI classes was taking 51 mins to complete but given long enough time it was completing; converting it to sets and applying pretty much the same logic got it down to 6 secs on machines with the highest amount of data!

4 Likes

51 minutes down to 6 seconds! 1x1x1x1 really works.

Can you PM me your final? - I want to consider using it in my session for Masterclass and real-world examples are very compelling.

Maybe you can convince your leaders to let you fly over for October? Would love to see you again in person.

1 Like