System.tag.browse OR in filter

Ignition 8.0.12
We like to use de system.tag.browse function to browse the tags in search for folders or udt instances.
Is this possible?
We have tried something like this:
results = system.tag.browse( path, {‘tagType’:‘Folder’} or {‘tagType’:‘UdtInstance’} )
but that does not give the desired results.
Can somebody give us a hint?

I had a bit of a play around, I think you’ll have to run two separate calls for this (unless someone else knows a way?)

This will give you what you need though:

#do browses
res1 = system.tag.browse(path, filter = {'tagType':'Folder'}).getResults()
res2 = system.tag.browse(path, filter = {'tagType':'UdtInstance'}).getResults()

#add results from second browse to first
for res in res2:
	res1.append(res)

#view all results
for result in res1:
	print result

1 Like

I think this wil not work correct when a UdtInstance contains one or more folders and when folders containing UdtInstances.

In that case you will need to use a recursive browse to go further into structure.

That is exactly where I need this function for.

This is my function for now. It is working, I only want to optimize the speed bij adding a filter in the folder part.

def browseTags( path='[default]', filter={}, resultaat=[] ):
	# see system.tag.browse() doc
 
	# Call the browse function for folders, do not use the filter
	results = system.tag.browse( path, {} )
#	results = system.tag.browse( path, {'tagType':'Folder'} or {'tagType':'UdtInstance'} ) # does not work
	for result in results.getResults():
		fullPath = str( result['fullPath'] )
		if result['hasChildren'] == True: # recursive call when folder or UdtInstance
			resultaat = browseTags( fullPath, filter, resultaat )
        
	# Call the browse function voor tags, use filter
	results = system.tag.browse( path, filter )
	for result in results.getResults():
		fullPath = str( result['fullPath'] )
		if result['hasChildren'] == False and fullPath.find( '_types_' ) == -1: # if not a tag-type then store
			resultaat.append( fullPath ) 
	
 	return resultaat   

# You can use this function like so:
tagpaths = browseTags( filter= {'name':'Audio*'} )     

2 Likes

This is exactly the issue I have with this new function, 1. that it doesn’t have a recursive argument/function like with the old one, and 2. that it’s so complicated and seemingly inefficient to search recursively for tags with a filter now :confused:
However, thanks for your function. I was about to write my own to do just this (surely everyone using v8 has either written their own or borrowed someone else’s from the forum… which begs the question why it isn’t still a part of the in-built function)

Actually, though it’s undocumented, you can add "recursive": True to the filter parameters and it’ll make a recursive call.

1 Like

Thanks @PGriffith, I’ll give it a go. Not sure why it’s undocumented as the function is a bit useless without recursion imo.
Also, is it possible to get documentation added for the filter values? The only reason I knew that data type needed the enum int value was due to the error I got trying to use the name “Int2”.
Also2, how can we supply multiple criteria?

While adding that 'recursive': True does seem to do a recursive search, the fullPath members of the returned results does not seem to contain the folder path. So perhaps it is not ready for primetime (and thus why it is still undocumented)?

1 Like

Yes, fixing the paths is part of the effort tied up in the ‘document the recursive filter’ ticket.

1 Like

Can we supply multiple criteria per filter type? (e.g multiple dataTypes Int2 or Boolean)

No, it looks like the property filtering is inclusive, so all supplied properties have to be present. Adding a second data type would just replace the first. The only exception is name, which should allow multiple values.

Do you know if there are any plans on changing (fixing :slight_smile: ) this?

@PGriffith can you advise how to use a multi-filter on name within system.tag.browse? I see the capability with:
system.tag.browseHistoricalTags(path, [nameFilters], [maxSize], [continuationPoint])

The name filter accepts a single string with wildcards (*), eg 'Status*' . It doesn't accept multiple conditions for eg in a list.

If you want to return tags with multiple conditions, youll have to post process the returned list

1 Like

Well, technically, the way the code is written, you could do something terrible like this for the name condition. I have no idea if this will actually return useful results though:

class FakeKey():
	def toString(self):
		return "name"
		
filters = {
	FakeKey(): "Realistic*",
	FakeKey(): "Other*",
}

system.tag.browse("", filters)

When using the following command, it appears that the last defined value for 'name' is the one that is actually used. I think my command matches the intent on yours?

system.tag.browse(dataSource, filter = {'tagType':'Folder', 'name':'n1','name':'n2', }).getResults()

I'm using Ignition 8.1.21

Instantiating a dict like that isn't doing anything:

>>> d = {'name': 2, 'name':3}
>>> d
{'name': 3}

You have to use an extra class so that the keys aren't automatically merged.

Am not sure to understand.
If I try to browse and get multiple instance UDT at the same time what is gonna be the script?
I try:

results = system.tag.browse("[default]", {"typeId" : "VALVE_DDT", "typeId" : "MOTOR_DDT","tagType":"UdtInstance","recursive":True}).results
for result in results:
	print str(result['fullPath'])
	

and I try like your said(But am not sure to understand very well):

Filter = {'typeId': "MOTOR_DDT", 'typeId': "VALVE_DDT","tagType":"UdtInstance","recursive":True}

results = system.tag.browse("[default]", Filter).results
for result in results:
	print str(result['fullPath'])