diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bda0d3..3b5b380 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [v0.6.2] + +- Add [#69]: add faceted search to web UI. +- Add [#61]: add faceted search to CLI app. + ## [v0.6.1] - Add [#67]: score details for web-UI. @@ -99,6 +104,8 @@ This document follows [changelog guidelines] +[v0.6.2]: https://github.com/gnames/gnverifier/compare/v0.6.1...v1.6.2 +[v0.6.1]: https://github.com/gnames/gnverifier/compare/v0.6.0...v1.6.1 [v0.6.0]: https://github.com/gnames/gnverifier/compare/v0.5.2...v1.6.0 [v0.5.2]: https://github.com/gnames/gnverifier/compare/v0.5.1...v0.5.2 [v0.5.1]: https://github.com/gnames/gnverifier/compare/v0.5.0...v0.5.1 @@ -117,6 +124,16 @@ This document follows [changelog guidelines] [v0.2.0]: https://github.com/gnames/gnverifier/compare/v0.1.0...v0.2.0 [v0.1.0]: https://github.com/gnames/gnverifier/tree/v0.1.0 +[#80]: https://github.com/gnames/gnverifier/issues/80 +[#79]: https://github.com/gnames/gnverifier/issues/79 +[#78]: https://github.com/gnames/gnverifier/issues/78 +[#77]: https://github.com/gnames/gnverifier/issues/77 +[#76]: https://github.com/gnames/gnverifier/issues/76 +[#75]: https://github.com/gnames/gnverifier/issues/75 +[#74]: https://github.com/gnames/gnverifier/issues/74 +[#73]: https://github.com/gnames/gnverifier/issues/73 +[#72]: https://github.com/gnames/gnverifier/issues/72 +[#71]: https://github.com/gnames/gnverifier/issues/71 [#70]: https://github.com/gnames/gnverifier/issues/70 [#69]: https://github.com/gnames/gnverifier/issues/69 [#68]: https://github.com/gnames/gnverifier/issues/68 diff --git a/README.md b/README.md index 688c335..0336fae 100644 --- a/README.md +++ b/README.md @@ -353,6 +353,8 @@ gnverifier file.txt ### Advanced Search Query Language +Example: `g:M. sp:gallop. au:Oliv. y:1750-1799` + Query language allows searching for scientific names using name components like genus name, specific epithet, infraspecific epithet, author, year. It includes following operators: diff --git a/gnverifier/cmd/root.go b/gnverifier/cmd/root.go index 84d9fb0..fdebe7e 100644 --- a/gnverifier/cmd/root.go +++ b/gnverifier/cmd/root.go @@ -12,12 +12,12 @@ import ( "strings" "sync" "time" - "unicode" "github.com/dustin/go-humanize" "github.com/gnames/gnfmt" vlib "github.com/gnames/gnlib/ent/verifier" "github.com/gnames/gnquery" + "github.com/gnames/gnquery/ent/search" "github.com/gnames/gnsys" "github.com/gnames/gnverifier" "github.com/gnames/gnverifier/config" @@ -321,29 +321,13 @@ func verify(gnv gnverifier.GNverifier, str string) { } verifyFile(gnv, f) f.Close() - } else if isQuery(str) { + } else if search.IsQuery(str) { searchQuery(gnv, str) } else { verifyString(gnv, str) } } -func isQuery(s string) bool { - s = strings.TrimSpace(s) - idx := strings.Index(s, ":") - if idx == -1 { - return false - } - - rs := []rune(s[0:idx]) - for i := range rs { - if !unicode.IsLower(rs[i]) { - return false - } - } - return true -} - func verifyFile(gnv gnverifier.GNverifier, f io.Reader) { batch := gnv.Config().Batch in := make(chan []string) diff --git a/go.mod b/go.mod index 4c51dcc..4071604 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/dustin/go-humanize v1.0.0 github.com/gnames/gnfmt v0.2.0 github.com/gnames/gnlib v0.6.6 - github.com/gnames/gnquery v0.1.14 + github.com/gnames/gnquery v0.2.0 github.com/gnames/gnsys v0.2.2 github.com/gnames/gnuuid v0.1.1 github.com/labstack/echo/v4 v4.6.1 diff --git a/go.sum b/go.sum index 1c249e0..152e86d 100644 --- a/go.sum +++ b/go.sum @@ -103,8 +103,8 @@ github.com/gnames/gnparser v1.5.5/go.mod h1:prvrAYGrtT/LxN8ovG3LFojgjR7VDcao/cNW github.com/gnames/gnparser v1.5.7 h1:Spn1Zvm9FEpAGlV7L380x3DdCWmX8X3YGORC7jGDd0U= github.com/gnames/gnparser v1.5.7/go.mod h1:prvrAYGrtT/LxN8ovG3LFojgjR7VDcao/cNWYjUyYw0= github.com/gnames/gnquery v0.1.2/go.mod h1:Jm0ZiyZ8nd4+7Pu9xdGRi5F8q6XsCADUfDIfeH+oAjs= -github.com/gnames/gnquery v0.1.14 h1:FtAwykap5xt/kl33/CsFIZRIH3cQ08EllCQ5ETOg5rU= -github.com/gnames/gnquery v0.1.14/go.mod h1:FuY6vibVjaR6AZpi1+dXBzE5c6POyu8Bwb0hgR/OqGQ= +github.com/gnames/gnquery v0.2.0 h1:GW9ShVG1t0wJTCZb0A4JtDpgWCfAmciMhw2wX/0VtLc= +github.com/gnames/gnquery v0.2.0/go.mod h1:FuY6vibVjaR6AZpi1+dXBzE5c6POyu8Bwb0hgR/OqGQ= github.com/gnames/gnsys v0.2.2 h1:7IG4aKdCQzzP1tBFp6I9s75QSwM/qhMjpyQVQsedQUY= github.com/gnames/gnsys v0.2.2/go.mod h1:xCjepsCm9yJWTpIfDGt0sUJBLoFRGzH0I3F6ast+Bow= github.com/gnames/gnuuid v0.1.1 h1:UMRHYUSlD19qo8oVz1JyU57kg4yu+SJ/b+yvWYeqRiA= diff --git a/io/web/server.go b/io/web/server.go index 2f2f627..1c8bd93 100644 --- a/io/web/server.go +++ b/io/web/server.go @@ -11,11 +11,15 @@ import ( "github.com/gnames/gnfmt" vlib "github.com/gnames/gnlib/ent/verifier" + "github.com/gnames/gnquery" + "github.com/gnames/gnquery/ent/search" + "github.com/gnames/gnuuid" "github.com/gnames/gnverifier" "github.com/gnames/gnverifier/config" "github.com/gnames/gnverifier/ent/output" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" + "github.com/labstack/gommon/log" ) const withLogs = false @@ -249,7 +253,32 @@ func verificationResults( } gnv = gnv.ChangeConfig(opts...) - data.Verified = gnv.VerifyBatch(names) + if search.IsQuery(names[0]) { + var err error + inp := gnquery.New().Parse(names[0]) + ds := gnv.Config().DataSources + if len(ds) > 0 { + if ds[0] == 0 { + inp.WithAllResults = true + } else { + inp.DataSourceIDs = ds + } + } + data.Verified, err = gnv.Search(inp) + if err != nil { + log.Warn(err) + } + if len(data.Verified) == 0 { + data.Verified = []vlib.Name{ + { + ID: gnuuid.New(inp.Query).String(), + Name: inp.Query, + }, + } + } + } else { + data.Verified = gnv.VerifyBatch(names) + } if prefOnly { for i := range data.Verified { data.Verified[i].BestResult = nil diff --git a/io/web/templates.go b/io/web/templates.go index e6c8a55..1b37e91 100644 --- a/io/web/templates.go +++ b/io/web/templates.go @@ -104,11 +104,12 @@ func addFuncs(tmpl *template.Template) { }, "scoreDetails": func(sd vlib.ScoreDetails) template.HTML { curSrc := "Curated Source" + rank := "Rank Matched" sds := []struct { name string val float32 }{ - {"Rank Matched", sd.InfraSpecificRankScore}, + {rank, sd.InfraSpecificRankScore}, {"Not Fuzzy", sd.FuzzyLessScore}, {curSrc, sd.CuratedDataScore}, {"Authors/Year Match", sd.AuthorMatchScore}, @@ -120,7 +121,7 @@ func addFuncs(tmpl *template.Template) { var res []string for _, v := range sds { switch { - case v.val < 0.3: + case (v.name == rank && v.val < 1.0) || v.val < 0.3: color = "#aaa" case (v.name == curSrc && v.val > 0.5) || v.val == 1: color = "#080" @@ -145,6 +146,8 @@ func addFuncs(tmpl *template.Template) { switch mt { case vlib.Exact: res = fmt.Sprintf(" %s match by canonical form", clr["green"], mt) + case vlib.FacetedSearch: + res = fmt.Sprintf(" %s match", clr["green"], mt) case vlib.NoMatch: res = fmt.Sprintf(" %s", clr["red"], mt) case vlib.Fuzzy, vlib.PartialFuzzy: diff --git a/io/web/templates/home.html b/io/web/templates/home.html index 58ff7ca..f80754f 100644 --- a/io/web/templates/home.html +++ b/io/web/templates/home.html @@ -38,7 +38,13 @@
From selected Data Sources:
Optionally, it can also return matches from data-sources selected by a user.

-

Paste Scientific Names, one per line (up to 5,000 names)

+

+ Paste Scientific Names, one per line (up to 5,000 names)
or write an + Advanced Search Query + (ex: + g:B. sp:bubo au:Linn.). +

diff --git a/version.go b/version.go index 59b463a..f7845f2 100644 --- a/version.go +++ b/version.go @@ -2,7 +2,7 @@ package gnverifier var ( // Version of the gnverifier - Version = "v0.6.1+" + Version = "v0.6.2+" // Build timestamp Build = "n/a" )