Better string field indexing in Search

Hello,

I tried to use Search filters to quickly find ScriptableObjects in my card game. For example with a request like this:

t:CardData text:draw
But it didn’t work.

Search seems to only index strings with 5 to 32 characters without any special characters (even spaces). Other strings seems to be indexed for exact matches only.

It makes the tool way more limited that what I was expecting.

Am I missing something? Would it be possible to improve string indexing/searching? Or are we supposed to write our own tools for stuff like this and only use Search for the most basic searches?

t:CardData by itself brings up results?
Not sure about text: perhaps this needs quotes or only looks for exact matches (possibly even case sensitive) so perhaps text:draw or text: Draw might work.

Yes t:CardData works.
t:CardData Text:"complete card text" also works with exact matches (but that’s not very usefull).

According to the doc, property:string search for partial matches and property=string search for exact matches.

But, as I said, partial match seems to only work if the field value is a string with 5 to 32 characters without any special characters (I experimented a lot as it seemed random at first).

In any other case, only exact matches are found.

Disallowing partial string match searches for strings less than a certain length is a common optimization, otherwise too many results could tax the GUI or other systems. Typically it‘s a minimum of 3 or 4 characters but depends on the software. I can imagine that this is the case here but I can‘t say for certain.

No that’s not the problem. The length limit is not on the search pattern but on the string field of the assets.

For example if I create 4 cards:

    1. Text: “Draw 2 cards” (special characters)
    1. Text: “Draw2Cards”
    1. Text: “Draw” (less than 5 characters)
    1. Text: “Draw2cardsDraw2cardsDraw2cardsDraw2cards” (more than 32 characters)

t:CardData Text:dra will find only 2
t:CardData Text:draw will find 2 and 3 (because 3 is an exact match)
t:CardData text:"Draw 2 Cards" will find 1 (exact matches still work with special characters)

I think the reason behind this is the fact that all types are indexed as either string or number. This limitations make sense for the string representations of enums or colors for example. But not for most string fields.

Hi @Theta

you are right that the Search Index do not store complete string, only hashcode of string to be able to search as fast as possible. This is not problematic for most short strings. From memory we hash string results from 1 letter up to 32. I am surprised that in your case a string less than 5 characters. I will test this locally and see if I can repro.

Which version of Unity are you using?

Thanks for your feedback,

Seb

Hi @Theta I repro your use cases. I will investigate this further and fix what can be fixed. Thanks for reporting.

Hi @Theta

I have fixed most of the issues you have reported. For the time being all string properties bigger dans 32 characters are only indexed exactly.

That said, this is something you can modify in your project. You could create a custom indexer for your type of data (CadData) and specify how you want to index the properties. The following example should provide the functionality you are looking for:

using UnityEditor.Search;

public class CardDescriptionIndexer
{
    [CustomObjectIndexer(typeof(CardData))]
    static void IndexLongProperties(CustomObjectIndexerTarget target, ObjectIndexer indexer)
    {
        var card = target.target as CardData;
        if (card == null)
            return;

        // Note: we index the property under a different name (long_description) because the indexing system will override how indexing is done.
        // This will be fixed shortly: all custom indexers will be ran after the default indexers.

        // Note: see https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Search.ObjectIndexer.IndexPropertyComponents.html
        indexer.IndexPropertyComponents(target.documentIndex, "long_description", card.cardDescription);
    }
}

Then running the query
p: t:CardData long_description:draw

would yield the 4 cardDatas from your example

    1. Text: “Draw 2 cards” (special characters)
    1. Text: “Draw2Cards”
    1. Text: “Draw” (less than 5 characters)
    1. Text: “Draw2cardsDraw2cardsDraw2cardsDraw2cards” (more than 32 characters)

Thank you for your time.

I didn’t know about CustomObjectIndexer. Your script does what I wanted to do.