PrimalHQ / primal-caching-service

Primal’s caching service for Nostr connects to the specified set of relays, collects all events in real time, stores them locally, and makes them available to nostr clients through a web socket-based API.
https://primal.net
MIT License
86 stars 13 forks source link

Support NIP-50 search #16

Closed alexgleason closed 9 months ago

alexgleason commented 10 months ago

Related to #13

Adds support for NIP-50 search queries.

The following filters will work:

["REQ", "_", { "kinds": [0], "search": "alex", "limit": 5 }]
["REQ", "_", { "kinds": [1], "search": "hello" }]
["REQ", "_", { "search": "hello", "since": 0, "until": 1704225895165 }]

If you try to filter for unsupported kinds, it will error.

In the future, we should preprocess filters, and if a search filter doesn't have kinds, split it into two separate filters for [0] and [1].

alexgleason commented 10 months ago

I also created this version which supports empty kinds, but it has other problems:

            elseif haskey(filt, "search")
                kinds = get(filt, "kinds", [0, 1])
                for kind in kinds
                    if kind === 0
                        kwargs = [
                            :query=>filt["search"],
                            :limit=>get(filt, "limit", 10)
                        ]
                        app_funcall(:user_search, kwargs, sendres; subid, ws_id=ws_id)
                    elseif kind === 1
                        kwargs = [
                            :query=>filt["search"],
                            :limit=>get(filt, "limit", 20),
                            :since=>get(filt, "since", 0),
                            :until=>get(filt, "until", nothing)
                        ]
                        app_funcall(:search, kwargs, sendres; subid, ws_id=ws_id)
                    end
                end

This version is a little bit more beautiful and semantically correct, but the first filter will EOSE before the second one completes, which is worse behavior than this MR. It's because the cache handlers don't actually support multiple filters properly. So I still think this MR is better without other changes.