diff options
| author | Julie Qiu <julie@golang.org> | 2021-07-17 16:30:53 -0400 |
|---|---|---|
| committer | Julie Qiu <julie@golang.org> | 2021-07-20 13:21:56 +0000 |
| commit | 685af85aeb4e043f458dfed28947e8ef2dbb285e (patch) | |
| tree | 3a8042a71688adc5d6b901f528edd133f7a7cd1b /internal/postgres | |
| parent | 50446a6eb602460b5b27bb0976012ead8e6d32e7 (diff) | |
| download | go-x-pkgsite-685af85aeb4e043f458dfed28947e8ef2dbb285e.tar.xz | |
internal/postgres/{symbolsearch}: add QueryPackageDotSymbol
QueryPackageDotSymbol is added, which is used when the search input is
one word, contains one dot, and we assume that it has the structure
<package>.<symbol>.
For golang/go#44142
Change-Id: Ie08b32e9cbfba709aceed82dd9c3bde2bc22cfdc
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/335234
Trust: Julie Qiu <julie@golang.org>
Run-TryBot: Julie Qiu <julie@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Diffstat (limited to 'internal/postgres')
| -rw-r--r-- | internal/postgres/symbolsearch.go | 40 | ||||
| -rw-r--r-- | internal/postgres/symbolsearch/gen_query.go | 9 | ||||
| -rw-r--r-- | internal/postgres/symbolsearch/query.gen.go | 52 | ||||
| -rw-r--r-- | internal/postgres/symbolsearch/symbolsearch.go | 32 | ||||
| -rw-r--r-- | internal/postgres/symbolsearch_test.go | 9 |
5 files changed, 125 insertions, 17 deletions
diff --git a/internal/postgres/symbolsearch.go b/internal/postgres/symbolsearch.go index 0c82331b..48b72afc 100644 --- a/internal/postgres/symbolsearch.go +++ b/internal/postgres/symbolsearch.go @@ -8,6 +8,7 @@ import ( "context" "database/sql" "fmt" + "strings" "github.com/lib/pq" "golang.org/x/pkgsite/internal" @@ -111,15 +112,38 @@ func (db *DB) symbolSearch(ctx context.Context, q string, limit, offset, maxResu return nil } - // TODO: add additional queries based on q. - query := symbolsearch.QuerySymbol - err := db.db.RunQuery(ctx, query, collect, q, limit, offset) - if err != nil { - results = nil + var ( + query string + err error + ) + if len(strings.Fields(q)) == 1 { + switch len(strings.Split(q, ".")) { + case 1: + // There is only 1 word in the search, and there are no dots, so + // this must be the symbol name. + query = symbolsearch.QuerySymbol + case 2: + // There is only 1 element, split by 1 dot, so the search must + // either be for <package>.<symbol> or <type>.<methodOrFieldName>. + // TODO: implement + case 3: + // There is only 1 element, split by 2 dots, so the search must + // be for <package>.<type>.<methodOrFieldName>. + query = symbolsearch.QueryPackageDotSymbol + } + } else { + // TODO: add additional queries based on q. + err = fmt.Errorf("unsupported query structure: %q", q) } - if len(results) > 0 && results[0].NumResults > uint64(maxResultCount) { - for _, r := range results { - r.NumResults = uint64(maxResultCount) + if err == nil { + err = db.db.RunQuery(ctx, query, collect, q, limit, offset) + if err != nil { + results = nil + } + if len(results) > 0 && results[0].NumResults > uint64(maxResultCount) { + for _, r := range results { + r.NumResults = uint64(maxResultCount) + } } } return searchResponse{ diff --git a/internal/postgres/symbolsearch/gen_query.go b/internal/postgres/symbolsearch/gen_query.go index f0969ab2..9c5b58aa 100644 --- a/internal/postgres/symbolsearch/gen_query.go +++ b/internal/postgres/symbolsearch/gen_query.go @@ -45,7 +45,14 @@ package symbolsearch // QuerySymbol is used when the search query is only one word, with no dots. // In this case, the word must match a symbol name and ranking is completely // determined by the path_tokens. -%s`, formatQuery("QuerySymbol", symbolsearch.RawQuerySymbol)) +%s + +// QueryPackageDotSymbol is used when the search query is one element +// containing a dot, where the first part is assumed to be the package name and +// the second the symbol name. For example, "sql.DB" or "sql.DB.Begin". +%s`, + formatQuery("QuerySymbol", symbolsearch.RawQuerySymbol), + formatQuery("QueryPackageDotSymbol", symbolsearch.RawQueryPackageDotSymbol)) func formatQuery(name, query string) string { return fmt.Sprintf("const %s = `%s`", name, query) diff --git a/internal/postgres/symbolsearch/query.gen.go b/internal/postgres/symbolsearch/query.gen.go index 8ae4d235..6cf98fb4 100644 --- a/internal/postgres/symbolsearch/query.gen.go +++ b/internal/postgres/symbolsearch/query.gen.go @@ -57,3 +57,55 @@ ORDER BY package_path LIMIT $2 OFFSET $3;` + +// QueryPackageDotSymbol is used when the search query is one element +// containing a dot, where the first part is assumed to be the package name and +// the second the symbol name. For example, "sql.DB" or "sql.DB.Begin". +const QueryPackageDotSymbol = ` +WITH results AS ( + SELECT + s.name AS symbol_name, + sd.package_path, + sd.module_path, + sd.version, + sd.name AS package_name, + sd.synopsis, + sd.license_types, + sd.commit_time, + sd.imported_by_count, + ssd.package_symbol_id, + ssd.goos, + ssd.goarch, + (ln(exp(1)+imported_by_count) + * CASE WHEN sd.redistributable THEN 1 ELSE 0.500000 END + * CASE WHEN COALESCE(has_go_mod, true) THEN 1 ELSE 0.800000 END) AS score + FROM symbol_search_documents ssd + INNER JOIN search_documents sd ON sd.unit_id = ssd.unit_id + INNER JOIN symbol_names s ON s.id = ssd.symbol_name_id + WHERE sd.name = split_part($1, '.', 1) AND s.tsv_name_tokens @@ to_tsquery('symbols', substring(replace($1, '_', '-') from E'[^.]*\.(.+)$')) +) +SELECT + r.package_path, + r.module_path, + r.version, + r.package_name, + r.synopsis, + r.license_types, + r.commit_time, + r.imported_by_count, + r.symbol_name, + r.goos, + r.goarch, + ps.type AS symbol_type, + ps.synopsis AS symbol_synopsis, + COUNT(*) OVER() AS total +FROM results r +INNER JOIN package_symbols ps ON r.package_symbol_id = ps.id +WHERE r.score > 0.1 +ORDER BY + score DESC, + commit_time DESC, + symbol_name, + package_path +LIMIT $2 +OFFSET $3;` diff --git a/internal/postgres/symbolsearch/symbolsearch.go b/internal/postgres/symbolsearch/symbolsearch.go index dbba7d88..0229a385 100644 --- a/internal/postgres/symbolsearch/symbolsearch.go +++ b/internal/postgres/symbolsearch/symbolsearch.go @@ -19,15 +19,35 @@ import ( const SymbolTextSearchConfiguration = "symbols" -var RawQuerySymbol = fmt.Sprintf(symbolSearchBaseQuery, scoreSymbol, filterSymbol) +var ( + RawQuerySymbol = fmt.Sprintf(symbolSearchBaseQuery, scoreMultipliers, filterSymbol) + RawQueryPackageDotSymbol = fmt.Sprintf(symbolSearchBaseQuery, scoreMultipliers, filterPackageDotSymbol) +) -// filterSymbol is used when $1 is the full symbol name, either -// <symbol> or <type>.<methodOrField>. -var filterSymbol = fmt.Sprintf(`s.tsv_name_tokens @@ %s`, toTSQuery("$1")) +var ( + // filterSymbol is used when $1 is the full symbol name, either + // <symbol> or <type>.<methodOrField>. + filterSymbol = fmt.Sprintf(`s.tsv_name_tokens @@ %s`, toTSQuery("$1")) + + // filterPackageDotSymbol is used when $1 is either <package>.<symbol> OR + // <package>.<type>.<methodOrField>. + filterPackageDotSymbol = fmt.Sprintf( + // Split the package name from $1, which can be assumed to be the + // element preceding the first dot. + `sd.name = split_part($1, '.', 1) AND s.tsv_name_tokens @@ %s`, + // Split the symbol name from $1, which can be assumed to be everything + // following the first dot. + toTSQuery("substring($1 from E'[^.]*\\.(.+)$')")) +) var ( - // scoreSymbol is the score the for QuerySymbol. - scoreSymbol = fmt.Sprintf("%s\n\t\t* %s\n\t\t* %s", + // scoreMultipliers is the score of multiplying the multiplers. + // + // It is also used as the score for QuerySymbol and QueryPackageDotIdentifier. + // In both cases, the matching symbols will be filtered in the WHERE + // clause, and the only remaining information to rank the results by are + // the multiplers. + scoreMultipliers = fmt.Sprintf("%s\n\t\t* %s\n\t\t* %s", popularityMultiplier, redistributableMultipler, goModMultipler) // Popularity multipler to increase ranking of popular packages. diff --git a/internal/postgres/symbolsearch_test.go b/internal/postgres/symbolsearch_test.go index e97f19d9..b82e37f6 100644 --- a/internal/postgres/symbolsearch_test.go +++ b/internal/postgres/symbolsearch_test.go @@ -52,15 +52,20 @@ func TestSymbolSearch(t *testing.T) { want []*SearchResult }{ { - name: "test search by <identifier>", + name: "test search by <symbol>", q: sample.Variable.Name, want: checkResult(sample.Variable.SymbolMeta), }, { - name: "test search by <recv>", + name: "test search by <methodName>", q: "Method", want: checkResult(sample.Method), }, + { + name: "test search by <package>.<type>.<methodName>", + q: "foo.Type.Method", + want: checkResult(sample.Method), + }, /* { name: "test search by <package>.<identifier>", |
