I love Apple's Spotlight in theory, but in practice I hate the GUI implementation. On my 1.33Mhz G4 laptop, having it try to search while I'm still trying to type the first is both painful and usually useless. And, to make matters worse, when using Spotlight from the Finder, it seems to crash the finder about 50% of the time.

So, half the time I end up just using locate or find. But I keep thinking that I should really be using mdfind. But the manual page is less than helpful. It says

The query can be a string or a query expression.

which isn't very helpful because it doesn't tell you what valid query expressions look like.

Some people tell you to just do a search in the Finder, save it as a saved search/smart folder, and then go peek in ~/Library/Saved Searches. There you'll find evil XML (or binary) plist files, which are unreadable by normal people. But here's a useful trick to render them in human readable form (i.e., the old-style ASCII plist format). If the file ends with a .plist extension (e.g., ~/blah/foobar.plist), you can use defaults read ~/blah/foobar (note the lack of the .plist — the defaults command insists on adding it). If it doesn't end with .plist, you can make a temporary symlink that does.

So, you can look at saved searches, but learning from examples only goes so far. And, you can use mdls on existing known files to find potential attributes to use in your search.

But what you really need is to know the query expression syntax, and the metadata attributes. Why they can't just tell you about these references on the mdfind man page I don't know.

This documentation is a good start, except that it is still fairly sparse. From what I can tell, the inRange operator doesn't work, or at least doesn't work on dates. This works to find the files I've changed in the last day:

   mdfind '(kMDItemFSContentChangeDate >= $time.today(-1)) && (kMDItemFSContentChangeDate < $time.now) && (kMDItemContentTypeTree = "public.content")'

but this one doesn't

   mdfind '(inRange(kMDItemFSContentChangeDate,$time.today(-1),$time.now)) && (kMDItemContentTypeTree = "public.content")'

The kMDItemContentTypeTree = "public.content" part is to weed out updated cache files and the like, although apparently Makefiles don't qualify as content (none of the importers recognize them, I guess), so they get weeded out too. sigh

Still, I'm closer than ever to weaning myself off locate and find. Maybe.