coleifer / peewee

a small, expressive orm -- supports postgresql, mysql, sqlite and cockroachdb
http://docs.peewee-orm.com/
MIT License
11.06k stars 1.37k forks source link

Full text search with queries #2883

Closed fede-bello closed 4 months ago

fede-bello commented 4 months ago

I've been following the docs https://docs.peewee-orm.com/en/2.10.2/peewee/playhouse.html in order to implement a full text search. The thing is that my query is a sentence, not a word. For this reason I could't use the Match() function. I've done a workaround like:

def text_search_postgres(search_text):
    search_query = fn.phraseto_tsquery(search_text)
    exp1 = Expression(
        (fn.to_tsvector("english", Document.summary)),
        "@@",
        search_query,
    )
    exp2 = Expression(
        (fn.to_tsvector("english", Document.metadata.cast("text"))),
        "@@",
        search_query,
    )
    query = Document.select().where(exp1 | exp2)

and it works, but is there a more staightforward way to do this that I am just not finding? Something like a Match function but for phrases?

coleifer commented 4 months ago

First, is there a reason that you're using the docs for 2.10? We're currently on 3.17 and 2.10 is a very old release.

To answer your question, however, no there is just too much variety in the way people store and structure their search corpora. The best way is to wrap it up in helper functions as you intend to use it. Many people will wish to store the tsvector of their search content in an indexed TSVectorField (see docs).

I'd suggest something like the following:


def search_expression(text):
    query = fn.phraseto_tsquery(text)
    content = fn.to_tsvector('english', Document.summary.concat(' ').concat(Document.metadata.cast('text')))
    return Expression(content, '@@', query)

Document.select().where(search_expression('the search text'))

Note you may also wish to use websearch_to_tsquery.