Since you're allowing search based on text -- and I'm guessing this means they can match a substring rather than having to specify the whole string to match -- it's a much more difficult problem than if every field had a well-defined set of possible values. If it were playing cards, the suit would be one type and the other would be rank. In that case you could maintain a set of cards for each attribute value. Like, Set<Card> hearts
, Set<Card> clubs
, Set<Card> threes
, etc. If there are any fields of that sort where you could have them select from a drop-down list that would greatly reduce search time. (Give me the set of sixes intersect the set of clubs, now search those for text that matches X.)
For the fields that do need to be text-searchable, it may be a good idea to keep an index based on each word in the value. For instance, if one card's "character" value contained "Luke Skywalker, Jedi Knight" (Card id 96) and another was "Mace Windu, Jedi Master" (Card id 97) then you would keep a data structure somewhat like this:
Map<String, Set<Cards>> characterTerms
with (K,V) entries like this:
"luke" -> [96]
"skywalker" -> [96]
"jedi" -> [96,97]
"knight" -> [96]
"mace" -> [97]
"windu" -> [97]
"master" -> [97]
Then when a search is submitted for "Skyw*"
you could iterate over the keys in the characterTerms
map to see which one have substrings of "skyw"
. In this case, the second entry. So you take that set of cards and see which ones match the rest of the criteria specified.
A good library for doing this sort of full-text search is Apache Lucene.