Adds elasticsearch to the user and channel autocompletion functions (#10354)

* Adds elasticsearch to the user and channel autocompletion functions

* Implement channel store GetChannelsByIds test

* Style changes and govet fixes

* Add gofmt fixes

* Extract default channel search limit to a const

* Add StringSliceDiff function to the utils package

* Honor USER_SEARCH_MAX_LIMIT on the user autocomplete api handler

* Change the elasticsearch development image
This commit is contained in:
Miguel de la Cruz
2019-03-15 17:53:53 +00:00
committed by GitHub
parent 5dae08761c
commit 44887a0272
17 changed files with 461 additions and 13 deletions

View File

@@ -785,10 +785,10 @@ func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt, updateAt int64)
// Additionally propagate the write to the PublicChannels table.
if _, err := transaction.Exec(`
UPDATE
PublicChannels
SET
PublicChannels
SET
DeleteAt = :DeleteAt
WHERE
WHERE
Id = :ChannelId
`, map[string]interface{}{
"DeleteAt": deleteAt,
@@ -835,7 +835,7 @@ func (s SqlChannelStore) PermanentDeleteByTeam(teamId string) store.StoreChannel
// Additionally propagate the deletions to the PublicChannels table.
if _, err := transaction.Exec(`
DELETE FROM
PublicChannels
PublicChannels
WHERE
TeamId = :TeamId
`, map[string]interface{}{
@@ -881,7 +881,7 @@ func (s SqlChannelStore) PermanentDelete(channelId string) store.StoreChannel {
// Additionally propagate the deletion to the PublicChannels table.
if _, err := transaction.Exec(`
DELETE FROM
PublicChannels
PublicChannels
WHERE
Id = :ChannelId
`, map[string]interface{}{
@@ -1689,7 +1689,7 @@ func (s SqlChannelStore) RemoveAllDeactivatedMembers(channelId string) store.Sto
DELETE
FROM
ChannelMembers
WHERE
WHERE
UserId IN (
SELECT
Id
@@ -1838,6 +1838,24 @@ func (s SqlChannelStore) GetAll(teamId string) store.StoreChannel {
})
}
func (s SqlChannelStore) GetChannelsByIds(channelIds []string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
keys, params := MapStringsToQueryParams(channelIds, "Channel")
query := `SELECT * FROM Channels WHERE Id IN ` + keys + ` ORDER BY Name`
var channels []*model.Channel
_, err := s.GetReplica().Select(&channels, query, params)
if err != nil {
mlog.Error(fmt.Sprint(err))
result.Err = model.NewAppError("SqlChannelStore.GetChannelsByIds", "store.sql_channel.get_channels_by_ids.app_error", nil, "", http.StatusInternalServerError)
} else {
result.Data = channels
}
})
}
func (s SqlChannelStore) GetForPost(postId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
channel := &model.Channel{}
@@ -1942,8 +1960,7 @@ func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeD
c.TeamId = :TeamId
` + deleteFilter + `
%v
LIMIT 50
`
LIMIT ` + strconv.Itoa(model.CHANNEL_SEARCH_DEFAULT_LIMIT)
var channels model.ChannelList

View File

@@ -148,6 +148,7 @@ type ChannelStore interface {
GetChannelCounts(teamId string, userId string) StoreChannel
GetTeamChannels(teamId string) StoreChannel
GetAll(teamId string) StoreChannel
GetChannelsByIds(channelIds []string) StoreChannel
GetForPost(postId string) StoreChannel
SaveMember(member *model.ChannelMember) StoreChannel
UpdateMember(member *model.ChannelMember) StoreChannel

View File

@@ -5,6 +5,7 @@ package storetest
import (
"sort"
"strconv"
"strings"
"testing"
"time"
@@ -41,6 +42,7 @@ func TestChannelStore(t *testing.T, ss store.Store, s SqlSupplier) {
t.Run("Update", func(t *testing.T) { testChannelStoreUpdate(t, ss) })
t.Run("GetChannelUnread", func(t *testing.T) { testGetChannelUnread(t, ss) })
t.Run("Get", func(t *testing.T) { testChannelStoreGet(t, ss, s) })
t.Run("GetChannelsByIds", func(t *testing.T) { testChannelStoreGetChannelsByIds(t, ss) })
t.Run("GetForPost", func(t *testing.T) { testChannelStoreGetForPost(t, ss) })
t.Run("Restore", func(t *testing.T) { testChannelStoreRestore(t, ss) })
t.Run("Delete", func(t *testing.T) { testChannelStoreDelete(t, ss) })
@@ -432,6 +434,73 @@ func testChannelStoreGet(t *testing.T, ss store.Store, s SqlSupplier) {
s.GetMaster().Exec("TRUNCATE Channels")
}
func testChannelStoreGetChannelsByIds(t *testing.T, ss store.Store) {
o1 := model.Channel{}
o1.TeamId = model.NewId()
o1.DisplayName = "Name"
o1.Name = "aa" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
store.Must(ss.Channel().Save(&o1, -1))
u1 := &model.User{}
u1.Email = MakeEmail()
u1.Nickname = model.NewId()
store.Must(ss.User().Save(u1))
store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}, -1))
u2 := model.User{}
u2.Email = MakeEmail()
u2.Nickname = model.NewId()
store.Must(ss.User().Save(&u2))
store.Must(ss.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}, -1))
o2 := model.Channel{}
o2.TeamId = model.NewId()
o2.DisplayName = "Direct Name"
o2.Name = "bb" + model.NewId() + "b"
o2.Type = model.CHANNEL_DIRECT
m1 := model.ChannelMember{}
m1.ChannelId = o2.Id
m1.UserId = u1.Id
m1.NotifyProps = model.GetDefaultChannelNotifyProps()
m2 := model.ChannelMember{}
m2.ChannelId = o2.Id
m2.UserId = u2.Id
m2.NotifyProps = model.GetDefaultChannelNotifyProps()
store.Must(ss.Channel().SaveDirectChannel(&o2, &m1, &m2))
if r1 := <-ss.Channel().GetChannelsByIds([]string{o1.Id, o2.Id}); r1.Err != nil {
t.Fatal(r1.Err)
} else {
cl := r1.Data.([]*model.Channel)
if len(cl) != 2 {
t.Fatal("invalid returned channels, expected 2 and got " + strconv.Itoa(len(cl)))
}
if cl[0].ToJson() != o1.ToJson() {
t.Fatal("invalid returned channel")
}
if cl[1].ToJson() != o2.ToJson() {
t.Fatal("invalid returned channel")
}
}
nonexistentId := "abcd1234"
if r2 := <-ss.Channel().GetChannelsByIds([]string{o1.Id, nonexistentId}); r2.Err != nil {
t.Fatal(r2.Err)
} else {
cl := r2.Data.([]*model.Channel)
if len(cl) != 1 {
t.Fatal("invalid returned channels, expected 1 and got " + strconv.Itoa(len(cl)))
}
if cl[0].ToJson() != o1.ToJson() {
t.Fatal("invalid returned channel")
}
}
}
func testChannelStoreGetForPost(t *testing.T, ss store.Store) {
o1 := store.Must(ss.Channel().Save(&model.Channel{
TeamId: model.NewId(),

View File

@@ -418,6 +418,22 @@ func (_m *ChannelStore) GetDeletedByName(team_id string, name string) store.Stor
return r0
}
// GetChannelsByIds provides a mock funcion with given fields: channelIds
func (_m *ChannelStore) GetChannelsByIds(channelIds []string) store.StoreChannel {
ret := _m.Called(channelIds)
var r0 store.StoreChannel
if rf, ok := ret.Get(0).(func([]string) store.StoreChannel); ok {
r0 = rf(channelIds)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(store.StoreChannel)
}
}
return r0
}
// GetForPost provides a mock function with given fields: postId
func (_m *ChannelStore) GetForPost(postId string) store.StoreChannel {
ret := _m.Called(postId)