A way of collecting notes searching all attributes


(Malcolm) #1

I looked by not found the answer.

There are a number of useful search functions in TB e.g. find() and others which require the user to identify the attribute to be searched within in each note. At the same time there is a global find function in the menus to search all notes for a specific piece of text.

My question is whether a function exists to search in a similar way to the global cmd+f function which would allow agents to search through all notes without knowing a priori in which attribute the text needs to be found ? I haven’t seen it yet.


(Mark Anderson) #2

In short, No. There is no global, all-attributes Find feature


(Malcolm) #3

Thanks - I thought so but wanted to be sure. In my case when starting with TB three or four weeks ago I created many notes changing the attribute names to store the same information type fairly frequently. This was my TB discovery phase. This means I have notes with say the text “Soil Moisture” connected to user attributes such as $MyText, $Product, $Application etc…I’m cleaning up now assigning all notes with information on soil moisture the attribute $SatelliteProduct == “Soil Moisture”.

I’m using the global find provided by the TB environment. I only have 40-5o notes and perhaps 5 attributes to clean-up into one so the manual clean-up is ok. For several 1000s it would be more onerous.


(Mark Anderson) #4

Perhaps at a tangent, but a good strategy is to put things you want to search for in a discrete attribute. If you need clear sub-groups within your overall ‘tags’ (keywords), use discrete attributes.


(Galen Menzel) #5

I find Tinderbox’s built-in search leaves a lot to be desired, but you can improve things by using an agent.

This TBX file (57.8 KB) has a top-level agent that will search for notes that contain all of the words in its $Name. (Note that unlike in the built-in search, the words can appear in any order and need not be next to one another, or even in the same attribute.) You can specify which attributes the agent searches by setting the agent’s SearchAttributes key attribute. This search is potentially quite costly, since it will be common to search through the $Text of notes, so if the agent has no words in its name, it deactivates itself, and reactivates itself when a word is entered into its name.

I usually have one of these at the root level of my documents ready to go if the built-in search doesn’t get the job done.

This still doesn’t do what you’re really looking for, in terms of searching every attribute. But it’s easy to add a large set of attributes to search, which is not possible in the built-in search.


(Malcolm) #6

A brilliant answer from Galen - many thanks. I’m using the occasion to learn a little more about actions in TB. I understood the edict (which switches the agent on and off depending if there is a name or not). The code for the actual search is a little more mysterious.

eval($SearchAttributes(agent)).icontains($MyRegex(agent)); 

the left hand side is a concatenated string with the attribute values in each note to be searched, correct ? I assume that $MyRegex(agent) is then a list of search terms but I’m not sure what it looks like in practice. Can you give an example or explain a little more the mechanics ?


(Malcolm) #9

Thanks - in fact there are some useful TB idioms in you’re answer. In particular the distinction between attributes that carry information ($MyRegex as an example) for the computation and attributes that execute code ($AgentQuery).

In this case the answer I was looking for is plainly visible under $MyRegex.


(Galen Menzel) #10

Yes. In the context of the query, $SearchAttributes(agent) refers to the agent’s $SearchAttributes attribute (set to the string "$Name + $Text + $MyString" in the example document). When this string is evaled, it is evaluated in the context of the note the agent is examining, so the $Name, $Text, and $MyString of the note the agent is examining are concatenated together. This is then searched to see if it matches $MyRegex(agent).

$MyRegex is set by the agent’s $Edict. The edict uses the string .replace operator to put each word in the agent’s $Name into a non-consuming-match expression. (In the example document, the agent’s name of “foo bar” yields the $MyRegex (?=.*foo)(?=.*bar). Briefly this regular expression looks for “foo” anywhere in a string without consuming any of the string. It then looks for “bar” anywhere in the string without consuming any of the string.) The result is a regular expression that will match when every word present in $Name is present in the search string.


(Michael Prenez-Isbell) #11

thanks for reminding me of the eval statement, was trying to remember that.