diff options
author | Joram Wilander <jwawilander@gmail.com> | 2015-10-20 08:00:21 -0400 |
---|---|---|
committer | Joram Wilander <jwawilander@gmail.com> | 2015-10-20 08:00:21 -0400 |
commit | 460a82878a93ef040d2c9a1221992ed7aa808d86 (patch) | |
tree | 1a50fabf167714d614d58b1625813b34686d5fd5 /store | |
parent | 7d8e08ccf6211d3df78eb6cfd4a198df77072540 (diff) | |
parent | 995c5a276bb27f50332047684b4d8f4cfc02243b (diff) | |
download | chat-460a82878a93ef040d2c9a1221992ed7aa808d86.tar.gz chat-460a82878a93ef040d2c9a1221992ed7aa808d86.tar.bz2 chat-460a82878a93ef040d2c9a1221992ed7aa808d86.zip |
Merge pull request #1113 from hmhealey/plt716
PLT-716/717 Added from:, in:, and channel: search filters
Diffstat (limited to 'store')
-rw-r--r-- | store/sql_post_store.go | 128 | ||||
-rw-r--r-- | store/sql_post_store_test.go | 22 | ||||
-rw-r--r-- | store/store.go | 2 |
3 files changed, 91 insertions, 61 deletions
diff --git a/store/sql_post_store.go b/store/sql_post_store.go index 07077bd64..6971de9d7 100644 --- a/store/sql_post_store.go +++ b/store/sql_post_store.go @@ -407,15 +407,23 @@ var specialSearchChar = []string{ "@", } -func (s SqlPostStore) Search(teamId string, userId string, terms string, isHashtagSearch bool) StoreChannel { +func (s SqlPostStore) Search(teamId string, userId string, params *model.SearchParams) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} + termMap := map[string]bool{} + terms := params.Terms + + if terms == "" && params.InChannel == "" && params.FromUser == "" { + result.Data = []*model.Post{} + storeChannel <- result + return + } searchType := "Message" - if isHashtagSearch { + if params.IsHashtag { searchType = "Hashtags" for _, term := range strings.Split(terms, " ") { termMap[term] = true @@ -430,63 +438,85 @@ func (s SqlPostStore) Search(teamId string, userId string, terms string, isHasht var posts []*model.Post if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES { + // Parse text for wildcards + if wildcard, err := regexp.Compile("\\*($| )"); err == nil { + terms = wildcard.ReplaceAllLiteralString(terms, "* ") + } + } + searchQuery := ` + SELECT + * + FROM + Posts + WHERE + DeleteAt = 0 + POST_FILTER + AND ChannelId IN ( + SELECT + Id + FROM + Channels, + ChannelMembers + WHERE + Id = ChannelId + AND TeamId = :TeamId + AND UserId = :UserId + AND DeleteAt = 0 + CHANNEL_FILTER) + SEARCH_CLAUSE + ORDER BY CreateAt DESC + LIMIT 100` + + if params.InChannel != "" { + searchQuery = strings.Replace(searchQuery, "CHANNEL_FILTER", "AND Name = :InChannel", 1) + } else { + searchQuery = strings.Replace(searchQuery, "CHANNEL_FILTER", "", 1) + } + + if params.FromUser != "" { + searchQuery = strings.Replace(searchQuery, "POST_FILTER", ` + AND UserId IN ( + SELECT + Id + FROM + Users + WHERE + TeamId = :TeamId + AND Username = :FromUser)`, 1) + } else { + searchQuery = strings.Replace(searchQuery, "POST_FILTER", "", 1) + } + + if terms == "" { + // we've already confirmed that we have a channel or user to search for + searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1) + } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES { // Parse text for wildcards if wildcard, err := regexp.Compile("\\*($| )"); err == nil { terms = wildcard.ReplaceAllLiteralString(terms, ":* ") } - searchQuery := fmt.Sprintf(`SELECT - * - FROM - Posts - WHERE - DeleteAt = 0 - AND ChannelId IN (SELECT - Id - FROM - Channels, - ChannelMembers - WHERE - Id = ChannelId AND TeamId = $1 - AND UserId = $2 - AND DeleteAt = 0) - AND %s @@ to_tsquery($3) - ORDER BY CreateAt DESC - LIMIT 100`, searchType) - terms = strings.Join(strings.Fields(terms), " | ") - _, err := s.GetReplica().Select(&posts, searchQuery, teamId, userId, terms) - if err != nil { - result.Err = model.NewAppError("SqlPostStore.Search", "We encounted an error while searching for posts", "teamId="+teamId+", err="+err.Error()) - - } + searchClause := fmt.Sprintf("AND %s @@ to_tsquery(:Terms)", searchType) + searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", searchClause, 1) } else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL { - searchQuery := fmt.Sprintf(`SELECT - * - FROM - Posts - WHERE - DeleteAt = 0 - AND ChannelId IN (SELECT - Id - FROM - Channels, - ChannelMembers - WHERE - Id = ChannelId AND TeamId = ? - AND UserId = ? - AND DeleteAt = 0) - AND MATCH (%s) AGAINST (? IN BOOLEAN MODE) - ORDER BY CreateAt DESC - LIMIT 100`, searchType) - - _, err := s.GetReplica().Select(&posts, searchQuery, teamId, userId, terms) - if err != nil { - result.Err = model.NewAppError("SqlPostStore.Search", "We encounted an error while searching for posts", "teamId="+teamId+", err="+err.Error()) + searchClause := fmt.Sprintf("AND MATCH (%s) AGAINST (:Terms IN BOOLEAN MODE)", searchType) + searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", searchClause, 1) + } - } + queryParams := map[string]interface{}{ + "TeamId": teamId, + "UserId": userId, + "Terms": terms, + "InChannel": params.InChannel, + "FromUser": params.FromUser, + } + + _, err := s.GetReplica().Select(&posts, searchQuery, queryParams) + if err != nil { + result.Err = model.NewAppError("SqlPostStore.Search", "We encounted an error while searching for posts", "teamId="+teamId+", err="+err.Error()) } list := &model.PostList{Order: make([]string, 0, len(posts))} diff --git a/store/sql_post_store_test.go b/store/sql_post_store_test.go index 9a7679454..b2256417e 100644 --- a/store/sql_post_store_test.go +++ b/store/sql_post_store_test.go @@ -525,57 +525,57 @@ func TestPostStoreSearch(t *testing.T) { o5.Hashtags = "#secret #howdy" o5 = (<-store.Post().Save(o5)).Data.(*model.Post) - r1 := (<-store.Post().Search(teamId, userId, "corey", false)).Data.(*model.PostList) + r1 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "corey", IsHashtag: false})).Data.(*model.PostList) if len(r1.Order) != 1 && r1.Order[0] != o1.Id { t.Fatal("returned wrong search result") } - r3 := (<-store.Post().Search(teamId, userId, "new", false)).Data.(*model.PostList) + r3 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "new", IsHashtag: false})).Data.(*model.PostList) if len(r3.Order) != 2 && r3.Order[0] != o1.Id { t.Fatal("returned wrong search result") } - r4 := (<-store.Post().Search(teamId, userId, "john", false)).Data.(*model.PostList) + r4 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "john", IsHashtag: false})).Data.(*model.PostList) if len(r4.Order) != 1 && r4.Order[0] != o2.Id { t.Fatal("returned wrong search result") } - r5 := (<-store.Post().Search(teamId, userId, "matter*", false)).Data.(*model.PostList) + r5 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "matter*", IsHashtag: false})).Data.(*model.PostList) if len(r5.Order) != 1 && r5.Order[0] != o1.Id { t.Fatal("returned wrong search result") } - r6 := (<-store.Post().Search(teamId, userId, "#hashtag", true)).Data.(*model.PostList) + r6 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "#hashtag", IsHashtag: true})).Data.(*model.PostList) if len(r6.Order) != 1 && r6.Order[0] != o4.Id { t.Fatal("returned wrong search result") } - r7 := (<-store.Post().Search(teamId, userId, "#secret", true)).Data.(*model.PostList) + r7 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "#secret", IsHashtag: true})).Data.(*model.PostList) if len(r7.Order) != 1 && r7.Order[0] != o5.Id { t.Fatal("returned wrong search result") } - r8 := (<-store.Post().Search(teamId, userId, "@thisshouldmatchnothing", true)).Data.(*model.PostList) + r8 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "@thisshouldmatchnothing", IsHashtag: true})).Data.(*model.PostList) if len(r8.Order) != 0 { t.Fatal("returned wrong search result") } - r9 := (<-store.Post().Search(teamId, userId, "mattermost jersey", false)).Data.(*model.PostList) + r9 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "mattermost jersey", IsHashtag: false})).Data.(*model.PostList) if len(r9.Order) != 2 { t.Fatal("returned wrong search result") } - r10 := (<-store.Post().Search(teamId, userId, "matter* jer*", false)).Data.(*model.PostList) + r10 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "matter* jer*", IsHashtag: false})).Data.(*model.PostList) if len(r10.Order) != 2 { t.Fatal("returned wrong search result") } - r11 := (<-store.Post().Search(teamId, userId, "message blargh", false)).Data.(*model.PostList) + r11 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "message blargh", IsHashtag: false})).Data.(*model.PostList) if len(r11.Order) != 1 { t.Fatal("returned wrong search result") } - r12 := (<-store.Post().Search(teamId, userId, "blargh>", false)).Data.(*model.PostList) + r12 := (<-store.Post().Search(teamId, userId, &model.SearchParams{Terms: "blargh>", IsHashtag: false})).Data.(*model.PostList) if len(r12.Order) != 1 { t.Fatal("returned wrong search result") } diff --git a/store/store.go b/store/store.go index 70980a15c..27731cee1 100644 --- a/store/store.go +++ b/store/store.go @@ -84,7 +84,7 @@ type PostStore interface { GetPosts(channelId string, offset int, limit int) StoreChannel GetPostsSince(channelId string, time int64) StoreChannel GetEtag(channelId string) StoreChannel - Search(teamId string, userId string, terms string, isHashtagSearch bool) StoreChannel + Search(teamId string, userId string, params *model.SearchParams) StoreChannel GetForExport(channelId string) StoreChannel } |