github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/store/searchlayer/post_layer.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package searchlayer 5 6 import ( 7 "github.com/pkg/errors" 8 9 "github.com/mattermost/mattermost-server/v5/mlog" 10 "github.com/mattermost/mattermost-server/v5/model" 11 "github.com/mattermost/mattermost-server/v5/services/searchengine" 12 "github.com/mattermost/mattermost-server/v5/store" 13 ) 14 15 type SearchPostStore struct { 16 store.PostStore 17 rootStore *SearchStore 18 } 19 20 func (s SearchPostStore) indexPost(post *model.Post) { 21 for _, engine := range s.rootStore.searchEngine.GetActiveEngines() { 22 if engine.IsIndexingEnabled() { 23 runIndexFn(engine, func(engineCopy searchengine.SearchEngineInterface) { 24 channel, chanErr := s.rootStore.Channel().Get(post.ChannelId, true) 25 if chanErr != nil { 26 mlog.Error("Couldn't get channel for post for SearchEngine indexing.", mlog.String("channel_id", post.ChannelId), mlog.String("search_engine", engineCopy.GetName()), mlog.String("post_id", post.Id), mlog.Err(chanErr)) 27 return 28 } 29 if err := engineCopy.IndexPost(post, channel.TeamId); err != nil { 30 mlog.Warn("Encountered error indexing post", mlog.String("post_id", post.Id), mlog.String("search_engine", engineCopy.GetName()), mlog.Err(err)) 31 return 32 } 33 mlog.Debug("Indexed post in search engine", mlog.String("search_engine", engineCopy.GetName()), mlog.String("post_id", post.Id)) 34 }) 35 } 36 } 37 } 38 39 func (s SearchPostStore) deletePostIndex(post *model.Post) { 40 for _, engine := range s.rootStore.searchEngine.GetActiveEngines() { 41 if engine.IsIndexingEnabled() { 42 runIndexFn(engine, func(engineCopy searchengine.SearchEngineInterface) { 43 if err := engineCopy.DeletePost(post); err != nil { 44 mlog.Warn("Encountered error deleting post", mlog.String("post_id", post.Id), mlog.String("search_engine", engineCopy.GetName()), mlog.Err(err)) 45 return 46 } 47 mlog.Debug("Removed post from the index in search engine", mlog.String("search_engine", engineCopy.GetName()), mlog.String("post_id", post.Id)) 48 }) 49 } 50 } 51 } 52 53 func (s SearchPostStore) deleteChannelPostsIndex(channelID string) { 54 for _, engine := range s.rootStore.searchEngine.GetActiveEngines() { 55 if engine.IsIndexingEnabled() { 56 runIndexFn(engine, func(engineCopy searchengine.SearchEngineInterface) { 57 if err := engineCopy.DeleteChannelPosts(channelID); err != nil { 58 mlog.Warn("Encountered error deleting channel posts", mlog.String("channel_id", channelID), mlog.String("search_engine", engineCopy.GetName()), mlog.Err(err)) 59 return 60 } 61 mlog.Debug("Removed all channel posts from the index in search engine", mlog.String("channel_id", channelID), mlog.String("search_engine", engineCopy.GetName())) 62 }) 63 } 64 } 65 } 66 67 func (s SearchPostStore) deleteUserPostsIndex(userID string) { 68 for _, engine := range s.rootStore.searchEngine.GetActiveEngines() { 69 if engine.IsIndexingEnabled() { 70 runIndexFn(engine, func(engineCopy searchengine.SearchEngineInterface) { 71 if err := engineCopy.DeleteUserPosts(userID); err != nil { 72 mlog.Warn("Encountered error deleting user posts", mlog.String("user_id", userID), mlog.String("search_engine", engineCopy.GetName()), mlog.Err(err)) 73 return 74 } 75 mlog.Debug("Removed all user posts from the index in search engine", mlog.String("user_id", userID), mlog.String("search_engine", engineCopy.GetName())) 76 }) 77 } 78 } 79 } 80 81 func (s SearchPostStore) Update(newPost, oldPost *model.Post) (*model.Post, error) { 82 post, err := s.PostStore.Update(newPost, oldPost) 83 84 if err == nil { 85 s.indexPost(post) 86 } 87 return post, err 88 } 89 90 func (s *SearchPostStore) Overwrite(post *model.Post) (*model.Post, error) { 91 post, err := s.PostStore.Overwrite(post) 92 if err == nil { 93 s.indexPost(post) 94 } 95 return post, err 96 } 97 98 func (s SearchPostStore) Save(post *model.Post) (*model.Post, error) { 99 npost, err := s.PostStore.Save(post) 100 101 if err == nil { 102 s.indexPost(npost) 103 } 104 return npost, err 105 } 106 107 func (s SearchPostStore) Delete(postId string, date int64, deletedByID string) error { 108 err := s.PostStore.Delete(postId, date, deletedByID) 109 110 if err == nil { 111 postList, err2 := s.PostStore.Get(postId, true, false, false) 112 if postList != nil && len(postList.Order) > 0 { 113 if err2 != nil { 114 s.deletePostIndex(postList.Posts[postList.Order[0]]) 115 } 116 } 117 } 118 return err 119 } 120 121 func (s SearchPostStore) PermanentDeleteByUser(userID string) error { 122 err := s.PostStore.PermanentDeleteByUser(userID) 123 if err == nil { 124 s.deleteUserPostsIndex(userID) 125 } 126 return err 127 } 128 129 func (s SearchPostStore) PermanentDeleteByChannel(channelID string) error { 130 err := s.PostStore.PermanentDeleteByChannel(channelID) 131 if err == nil { 132 s.deleteChannelPostsIndex(channelID) 133 } 134 return err 135 } 136 137 func (s SearchPostStore) searchPostsInTeamForUserByEngine(engine searchengine.SearchEngineInterface, paramsList []*model.SearchParams, userId, teamId string, page, perPage int) (*model.PostSearchResults, error) { 138 if err := model.IsSearchParamsListValid(paramsList); err != nil { 139 return nil, err 140 } 141 142 // We only allow the user to search in channels they are a member of. 143 userChannels, err2 := s.rootStore.Channel().GetChannels(teamId, userId, paramsList[0].IncludeDeletedChannels, 0) 144 if err2 != nil { 145 return nil, errors.Wrap(err2, "error getting channel for user") 146 } 147 148 postIds, matches, err := engine.SearchPosts(userChannels, paramsList, page, perPage) 149 if err != nil { 150 return nil, err 151 } 152 153 // Get the posts 154 postList := model.NewPostList() 155 if len(postIds) > 0 { 156 posts, err := s.PostStore.GetPostsByIds(postIds) 157 if err != nil { 158 return nil, err 159 } 160 for _, p := range posts { 161 if p.DeleteAt == 0 { 162 postList.AddPost(p) 163 postList.AddOrder(p.Id) 164 } 165 } 166 } 167 168 return model.MakePostSearchResults(postList, matches), nil 169 } 170 171 func (s SearchPostStore) SearchPostsInTeamForUser(paramsList []*model.SearchParams, userId, teamId string, page, perPage int) (*model.PostSearchResults, error) { 172 for _, engine := range s.rootStore.searchEngine.GetActiveEngines() { 173 if engine.IsSearchEnabled() { 174 results, err := s.searchPostsInTeamForUserByEngine(engine, paramsList, userId, teamId, page, perPage) 175 if err != nil { 176 mlog.Warn("Encountered error on SearchPostsInTeamForUser.", mlog.String("search_engine", engine.GetName()), mlog.Err(err)) 177 continue 178 } 179 mlog.Debug("Using the first available search engine", mlog.String("search_engine", engine.GetName())) 180 return results, err 181 } 182 } 183 184 if *s.rootStore.getConfig().SqlSettings.DisableDatabaseSearch { 185 mlog.Debug("Returning empty results for post SearchPostsInTeam as the database search is disabled") 186 return &model.PostSearchResults{PostList: model.NewPostList(), Matches: model.PostSearchMatches{}}, nil 187 } 188 189 mlog.Debug("Using database search because no other search engine is available") 190 return s.PostStore.SearchPostsInTeamForUser(paramsList, userId, teamId, page, perPage) 191 }