Support of "contains" logic in full text search

For full text search, if the value of textSearchField field is something like

db_finance db_Finance description db_Finance

When I do search with matchesText,

matchesText(textSearchField, 'db') returns expected result,
matchesText(textSearchField, 'description') returns expected result.

But if I want to search with substring, like matchesText(textSearchField, 'desc'), it doesn’t return expected result.

I’m wondering if this substring search is not supported by design.

I don’t think there is api called matchesText, there are the following:

  /**
   * Check if input string matches provided regex pattern.
   *
   * Example: `matchesRegex(field, "[0-9-F-a-f]+")`
   *
   * @see #regexMatch
   * @see RegexPattern
   *
   * @param str
   *        string input to be matched
   * @param regex
   *        regex pattern
   * @return true if str matches the regex.
   */
  matchesRegex: function(str: !?string, regex: !string): boolean

  /**
   * Check if input string matches provided glob pattern.
   *
   * Example: `matchesGlob(url, "*abc/Test*.java")`
   *
   * @see #globMatch
   * @see GlobPattern
   *
   * @param str
   *        string input to be matched
   * @param glob
   *        glob pattern
   * @return true if str matches the glob.
   */
  matchesGlob: function(str: !?string, glob: !string): boolean

  /**
   * Check if input string matches provided CamelCase pattern.
   *
   * Example: `matchesCamelCase("AnotherBasicClass", "ABC")` will return `true`
   *          `matchesCamelCase("AnotherBasicClass", "xyz")` will return `false`.
   *
   * @see #camelCaseMatch
   * @see CamelCasePattern
   *
   * @param str
   *        string input to be matched
   * @param camelCase
   *        CamelCase pattern
   * @param allowLowerCamelCase
   *        should we match strings that start with lower case.
   * @return true if str matches the CamelCase pattern.
   */
  matchesCamelCase: function(str: !?string, camelCase: !string, allowLowerCamelCase: boolean): boolean

  /**
   * Compute match between given input string and regex pattern.
   *
   * @see #matchesRegex
   * @see RegexPattern
   *
   * @param str
   *        string input to be matched
   * @param regex
   *        regex pattern
   * @return match details
   */
  regexMatch: function(str: !?string, regex: !string): !StringPatternMatch

  /**
   * Compute match between given input string and glob pattern.
   *
   * @see #matchesGlob
   * @see GlobPattern
   *
   * @param str
   *        string input to be matched
   * @param glob
   *        glob pattern
   * @return match details
   */
  globMatch: function(str: !?string, glob: !string): !StringPatternMatch

  /**
   * Perform the standard string opertion `contains` on the given input.
   * Check if str1 contains str2
   *
   * Example: `contains("regional facility", "facility") returns true.`
   *
   * @param str1
   *        string container
   * @param str2
   *        string to be checked if contained by str1
   * @return boolean - if str1 contains str2.
   */
  contains: function(str1: string, str2: string): !boolean

  /**
   * Perform the standard string opertion `contains` on the given input,
   * but it ignores the case.
   * Check if str1 contains str2
   *
   * Example: `containsIgnoreCase("regional facility", "Facility") returns true.`
   *
   * @param str1
   *        string container
   * @param str2
   *        string to be checked if contained by str1
   * @return boolean - if str1 contains str2.
   */
  containsIgnoreCase: function(str1: string, str2: string): !boolean

If you simply try to use contains I believe it should work

@chenliu9 The matchesTest uses Postgres text searching described here:

https://www.postgresql.org/docs/9.6/functions-textsearch.html

I believe it “tokenizes” the input into what it believes are logical “words”. As such, it is not suitable for the type of contains search you are trying (e.g. “desc” isn’t a “word”). You can use the contains function in filtering to get that behavior. However, it will be very slow on large datasets.

@rohit.sureka matchesText does exit, there’s just no documentation for it. Like @trothwein mentioned, it uses the Postgres full-text search feature.

@chenliu9 There is also the annotation @db(textSearchField=true). If you’re searching over a lot of records, this annotation creates an index that is optimized for doing full-text searches. I’m not sure it will let you do partial word matches, but it might help with performance depending on how big your dataset is.

Thanks! To summarize, for full text search (aka, textSearchField), we could use

  1. matchesText filter which is using text searching in Postgres, but it doesn’t support contains search
  2. contains filter which does support contains search, but it will be very slow on large datasets.
1 Like