redis / redis-om-node

Object mapping, and more, for Redis and Node.js. Written in TypeScript.
MIT License
1.18k stars 80 forks source link

matchExact does not work if text has period #179

Closed laurentbourg closed 1 year ago

laurentbourg commented 1 year ago

I am not able to do retrieve data with a matchExact call on a username field of type text having a period in it, it return 0 entries. e.g username = "first.last"

little node js snippet show usage: query = query.and((search) => search.where("username").matchExact(req.query.username) ); if the username does not contain a period, it works well.

It seems the issue stems from the fact that the search is interpreting the dot as a nest field of the parent field. If that is the case, how do I escape characters or tag and attribute in the schema?

guyroyse commented 1 year ago

I suspect you have specified this field as a 'text' field and not a 'string'. 'text' fields are optimized for human-readable text. Like paragraphs of text, product descriptions, or song lyrics. As such, certain common words like a, an, the, or, etc. (i.e. stop words) are not searchable. And, punctuation is not searchable. The period is certainly being seen as punctuation in this case.

The better solution would be to set the username as a 'string'. This sets it up as a TAG field in RediSearch and will allow you to simply do this: search.where("username").equals(req.query.username)

In future version, I plan to have Redis OM index all 'string' fields as both TEXT and TAG in RediSearch as this confusion happens quite a bit.

laurentbourg commented 1 year ago

Thanks for your reply @guyroyse, much appreciated. Yes my username is of "text" type. So for use cases such as a username, where search needs to be exact in some situations (let's say for a social media app, retrieving posts for a specific username) or searchable such as 'give me all usernames starting with "bob"', there would need to be 2 separate fields: username_matchable: text and username_equatable:string, containing the same value, so that both use cases can be supported. Am I understanding this correctly?

guyroyse commented 1 year ago

Newer versions of RediSearch support wildcarding. You should be able to use a * with a 'string'.

For example: search.where("username").equals("bob*")

laurentbourg commented 1 year ago

Understood, thanks again. Great library btw.

guyroyse commented 1 year ago

Thanks and glad you like it. Sorry for taking so long to respond to this. Been on the road a lot the last several weeks.

laurentbourg commented 1 year ago

No worries at all