Searching for exact match with hash symbol

I often add “#ACTION” to my notes. I want to set up a Smart Group that finds these. I’ve also tried searching manually.

In both cases, I find that a search for something with a hash in front just ignores the hash. It will match “ACTION” as well as “#ACTION”.

How can I get it only to return documents with full match?

(As I side note - I use regular expressions all the time in other apps, so if regex ever get supported in DevonThink, then that would be a nice easy solution to this. But hopefully there’s a quicker solution in the meantime!)

DEVONthink doesn’t index the # character.

From help Documentation > Windows > Main Window:

Note: The search index contains alphanumeric characters as well as the following symbols: $€£¥%§

1 Like

You could try this script. Select one or more groups in the item list. The results are shown in a new window

-- Show search results for search term containing non-indexed character(s)

property theSearchTerm : "#ACTION"

tell application id "DNtp"
	try
		set theRecords to selected records
		if theRecords = {} then error "Please select some groups"
		
		set theResults to {}
		
		repeat with thisRecord in theRecords
			set thisRecord_Type to (type of thisRecord) as string
			if thisRecord_Type is in {"group", "«constant ****DTgr»"} then
				set thisRecord_UUID to uuid of thisRecord
				set theResults to theResults & (contents of database of thisRecord whose plain text contains theSearchTerm and uuid of parents contains thisRecord_UUID)
			end if
		end repeat
		
		set theWindow to open window for record (root of viewer window 1) with force
		set search results of theWindow to theResults
		activate
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

1 Like

Thanks, Pete - that looks like a good workaround; I’ll give that a go!

Meanwhile (for the DevonThink team) - is there any way I can put in a feature request for adding more characters to the index? I think the hash character would be particularly useful.

A workaround for my particular case is to turn on the option to convert hashtags to tags, which would then create an ACTION tag. The problem with this is that I find I have hundreds of tags, as it’ll pick up any random thing with a hash in front of it; so in my use case it’s not particularly useful. (Although if a feature was added to give a list of possible hastags, rather than all, that would become a great feature).

Another option I might try, is to use something like “%ACTION” in my documents, instead.

Thanks once again for the help

Adding prefixes to a tag has not been necessary for a long time. It only has inertia due to people adopting the process long ago and others thinking they were still necessary. Not saying they can’t be used (or useful), just saying that aren’t required.

That being said, the request is noted but we don’t want to just allow any and all characters to be added as (1) it bloats the index and (2) it can lead to indexing things you many not want indexed, for example, code in spam.

As much as I love REs: What you are asking for is fundamentally different from how DT works nowadays (or at least that’s what I think – I may be wrong, of course). In the background, it creates an index of words (excluding most of the non-word characters) which you can then search for with a lot of different operators. Since the index is probably cleverly organized (think balanced B-tree or something like that), it’s fast to search.

This would not work with REs, since they’d have to operate on the full text of all records. The word index doesn’t help in this context. But having to RE-match each and every single record in a database would probably be a disappointing experience for users.

@pete31’s script is a very good compromise, I think, since it uses the whose operator that is blazingly fast (and does unfortunately not allow for REs). You could simply add a dialog to it to ask the user for the search expression and get a very flexible method to search.

1 Like

Agreed, @chrillek. This script with a dialogue to ask for any user input with non-indexed characters could be really useful in different scenarios.

@pete31 would program this more elegantly, I’m sure, but this should provide you with an input dialogue:

-- Show search results for search term containing non-indexed character(s)

tell application id "DNtp"
	try
		set theRecords to selected records
		if theRecords = {} then error "Please select some groups"
		
		set theResults to {}
		set dAnswer to "#Action"
		set userEntry to display dialog ¬
			"Enter the non-indexed character you wish to find" default answer dAnswer with title "Find a non-indexed character"
		set theSearchTerm to text returned of userEntry
		
		repeat with thisRecord in theRecords
			set thisRecord_Type to (type of thisRecord) as string
			if thisRecord_Type is in {"group", "«constant ****DTgr»"} then
				set thisRecord_UUID to uuid of thisRecord
				set theResults to theResults & (contents of database of thisRecord whose plain text contains theSearchTerm and uuid of parents contains thisRecord_UUID)
			end if
		end repeat
		
		set theWindow to open window for record (root of viewer window 1) with force
		set search results of theWindow to theResults
		activate
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

Stephen

2 Likes

Thank you @Stephen_C, this works. And of course to @pete31 for coming up with the script!

@pete31

After some further experimentation, I wanted to share an observation related to running the script in a very large database:

Even if only a single group with two markdown documents is selected before running the script, there is a spinning wheel and no results are returned (i.e. DT freezes). If the same group is moved into a normal-sized database, then everything works perfectly.

Is there potentially a fix for this, or anything I could try from my side?

I don’t there’s anything that could be done.

As a workaround, duplicating groups to be searched into a temporary database is an okay solution. Again, I admittedly have a very large database - not saying anything is wrong with the script.

1 Like

Please try this version

-- Show search results for search term containing non-indexed character(s)

property theSearchTerm : "#ACTION"

tell application id "DNtp"
	try
		set theRecords to selected records
		if theRecords = {} then error "Please select some groups"
		
		set theResults to {}
		
		repeat with thisRecord in theRecords
			set thisRecord_Type to (type of thisRecord) as string
			if thisRecord_Type is in {"group", "«constant ****DTgr»"} then
				set thisRecord_UUID to uuid of thisRecord
				set theResults to theResults & (contents of database of thisRecord whose uuid of parents contains thisRecord_UUID and plain text contains theSearchTerm)
			end if
		end repeat
		
		set theWindow to open window for record (root of viewer window 1) with force
		set search results of theWindow to theResults
		activate
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

2 Likes

I’m not sure why the script searches through the whole database, ie all records. That will of course take a longer time for a bigger database.

I could imagine to have the script iterate over the selected groups and only search in them (one after the other, that is).

But maybe there’s a reason to search through the complete database…

This solved it! Genius! Much appreciated.

1 Like

Great!

The “trick” is to first ask for the parent UUIDs and afterwards for the plain text.

A whose query evaluates from left to right, i.e. if a record doesn’t match the first part the next query part isn’t evaluated.

1 Like

It’s not possible to use contents directly with a group, only with the whole database. But by checking the parent UUIDs we can filter the database, i.e. only consider records that are a child of one of the selected records.

Search in children of the group with whose?

Not directly. Search in the whole database but search for records whose location is one of the selected records (or that are replicated into one of them). If that’s the case then get the plain text.

Pete is referring to this line, I believe. In the second script, which works with my large database, the order of the two criteria has been switched (below code is the revised version).

set theResults to theResults & (contents of database of thisRecord whose uuid of parents contains thisRecord_UUID and plain text contains theSearchTerm)

My understanding is that in the first version of the script, it would try to search the plain text of ALL items contained in the database for the search term, and then filter the set of returned items to include only those with parent groups’ IDs. In the second version, it first gets the correct groups and then only searches contained items for the search term, so now the database size is no longer an issue.

2 Likes