mirror of
https://github.com/hoernschen/dendrite.git
synced 2025-07-31 05:12:46 +00:00
Fulltext implementation using Bleve (#2675)
Based on #2480 This actually indexes events based on their event type. They are removed from the index if we receive a `m.room.redaction` event on the `OutputRoomEvent` stream. An admin endpoint is added to reindex all existing events. Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
This commit is contained in:
parent
6c67552bf9
commit
87be32ca26
22 changed files with 680 additions and 53 deletions
|
@ -161,6 +161,7 @@ type Database interface {
|
|||
// returns "leave", the topological position and no error. If an error occurs, other than sql.ErrNoRows, returns that and an empty
|
||||
// string as the membership.
|
||||
SelectMembershipForUser(ctx context.Context, roomID, userID string, pos int64) (membership string, topologicalPos int, err error)
|
||||
ReIndex(ctx context.Context, limit, afterID int64) (map[int64]gomatrixserverlib.HeaderedEvent, error)
|
||||
}
|
||||
|
||||
type Presence interface {
|
||||
|
|
|
@ -166,6 +166,8 @@ const selectContextAfterEventSQL = "" +
|
|||
" AND ( $7::text[] IS NULL OR NOT(type LIKE ANY($7)) )" +
|
||||
" ORDER BY id ASC LIMIT $3"
|
||||
|
||||
const selectSearchSQL = "SELECT id, event_id, headered_event_json FROM syncapi_output_room_events WHERE id > $1 AND type = ANY($2) ORDER BY id ASC LIMIT $3"
|
||||
|
||||
type outputRoomEventsStatements struct {
|
||||
insertEventStmt *sql.Stmt
|
||||
selectEventsStmt *sql.Stmt
|
||||
|
@ -180,6 +182,7 @@ type outputRoomEventsStatements struct {
|
|||
selectContextEventStmt *sql.Stmt
|
||||
selectContextBeforeEventStmt *sql.Stmt
|
||||
selectContextAfterEventStmt *sql.Stmt
|
||||
selectSearchStmt *sql.Stmt
|
||||
}
|
||||
|
||||
func NewPostgresEventsTable(db *sql.DB) (tables.Events, error) {
|
||||
|
@ -215,6 +218,7 @@ func NewPostgresEventsTable(db *sql.DB) (tables.Events, error) {
|
|||
{&s.selectContextEventStmt, selectContextEventSQL},
|
||||
{&s.selectContextBeforeEventStmt, selectContextBeforeEventSQL},
|
||||
{&s.selectContextAfterEventStmt, selectContextAfterEventSQL},
|
||||
{&s.selectSearchStmt, selectSearchSQL},
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
||||
|
@ -632,3 +636,27 @@ func rowsToStreamEvents(rows *sql.Rows) ([]types.StreamEvent, error) {
|
|||
}
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
||||
func (s *outputRoomEventsStatements) ReIndex(ctx context.Context, txn *sql.Tx, limit, afterID int64, types []string) (map[int64]gomatrixserverlib.HeaderedEvent, error) {
|
||||
rows, err := sqlutil.TxStmt(txn, s.selectSearchStmt).QueryContext(ctx, afterID, pq.StringArray(types), limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer internal.CloseAndLogIfError(ctx, rows, "rows.close() failed")
|
||||
|
||||
var eventID string
|
||||
var id int64
|
||||
result := make(map[int64]gomatrixserverlib.HeaderedEvent)
|
||||
for rows.Next() {
|
||||
var ev gomatrixserverlib.HeaderedEvent
|
||||
var eventBytes []byte
|
||||
if err = rows.Scan(&id, &eventID, &eventBytes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = ev.UnmarshalJSONWithEventID(eventBytes, eventID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[id] = ev
|
||||
}
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
|
|
@ -1093,3 +1093,11 @@ func (d *Database) MaxStreamPositionForPresence(ctx context.Context) (types.Stre
|
|||
func (d *Database) SelectMembershipForUser(ctx context.Context, roomID, userID string, pos int64) (membership string, topologicalPos int, err error) {
|
||||
return d.Memberships.SelectMembershipForUser(ctx, nil, roomID, userID, pos)
|
||||
}
|
||||
|
||||
func (s *Database) ReIndex(ctx context.Context, limit, afterID int64) (map[int64]gomatrixserverlib.HeaderedEvent, error) {
|
||||
return s.OutputEvents.ReIndex(ctx, nil, limit, afterID, []string{
|
||||
gomatrixserverlib.MRoomName,
|
||||
gomatrixserverlib.MRoomTopic,
|
||||
"m.room.message",
|
||||
})
|
||||
}
|
||||
|
|
|
@ -115,6 +115,8 @@ const selectContextAfterEventSQL = "" +
|
|||
|
||||
// WHEN, ORDER BY and LIMIT are appended by prepareWithFilters
|
||||
|
||||
const selectSearchSQL = "SELECT id, event_id, headered_event_json FROM syncapi_output_room_events WHERE type IN ($1) AND id > $2 LIMIT $3 ORDER BY id ASC"
|
||||
|
||||
type outputRoomEventsStatements struct {
|
||||
db *sql.DB
|
||||
streamIDStatements *StreamIDStatements
|
||||
|
@ -125,6 +127,7 @@ type outputRoomEventsStatements struct {
|
|||
selectContextEventStmt *sql.Stmt
|
||||
selectContextBeforeEventStmt *sql.Stmt
|
||||
selectContextAfterEventStmt *sql.Stmt
|
||||
//selectSearchStmt *sql.Stmt - prepared at runtime
|
||||
}
|
||||
|
||||
func NewSqliteEventsTable(db *sql.DB, streamID *StreamIDStatements) (tables.Events, error) {
|
||||
|
@ -157,6 +160,7 @@ func NewSqliteEventsTable(db *sql.DB, streamID *StreamIDStatements) (tables.Even
|
|||
{&s.selectContextEventStmt, selectContextEventSQL},
|
||||
{&s.selectContextBeforeEventStmt, selectContextBeforeEventSQL},
|
||||
{&s.selectContextAfterEventStmt, selectContextAfterEventSQL},
|
||||
//{&s.selectSearchStmt, selectSearchSQL}, - prepared at runtime
|
||||
}.Prepare(db)
|
||||
}
|
||||
|
||||
|
@ -628,3 +632,40 @@ func unmarshalStateIDs(addIDsJSON, delIDsJSON string) (addIDs []string, delIDs [
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *outputRoomEventsStatements) ReIndex(ctx context.Context, txn *sql.Tx, limit, afterID int64, types []string) (map[int64]gomatrixserverlib.HeaderedEvent, error) {
|
||||
params := make([]interface{}, len(types))
|
||||
for i := range types {
|
||||
params[i] = types[i]
|
||||
}
|
||||
params = append(params, afterID)
|
||||
params = append(params, limit)
|
||||
selectSQL := strings.Replace(selectSearchSQL, "($1)", sqlutil.QueryVariadic(len(types)), 1)
|
||||
|
||||
stmt, err := s.db.Prepare(selectSQL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer internal.CloseAndLogIfError(ctx, stmt, "selectEvents: stmt.close() failed")
|
||||
rows, err := stmt.QueryContext(ctx, params...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer internal.CloseAndLogIfError(ctx, rows, "rows.close() failed")
|
||||
|
||||
var eventID string
|
||||
var id int64
|
||||
result := make(map[int64]gomatrixserverlib.HeaderedEvent)
|
||||
for rows.Next() {
|
||||
var ev gomatrixserverlib.HeaderedEvent
|
||||
var eventBytes []byte
|
||||
if err = rows.Scan(&id, &eventID, &eventBytes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = ev.UnmarshalJSONWithEventID(eventBytes, eventID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[id] = ev
|
||||
}
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ type Events interface {
|
|||
SelectContextEvent(ctx context.Context, txn *sql.Tx, roomID, eventID string) (int, gomatrixserverlib.HeaderedEvent, error)
|
||||
SelectContextBeforeEvent(ctx context.Context, txn *sql.Tx, id int, roomID string, filter *gomatrixserverlib.RoomEventFilter) ([]*gomatrixserverlib.HeaderedEvent, error)
|
||||
SelectContextAfterEvent(ctx context.Context, txn *sql.Tx, id int, roomID string, filter *gomatrixserverlib.RoomEventFilter) (int, []*gomatrixserverlib.HeaderedEvent, error)
|
||||
ReIndex(ctx context.Context, txn *sql.Tx, limit, offset int64, types []string) (map[int64]gomatrixserverlib.HeaderedEvent, error)
|
||||
}
|
||||
|
||||
// Topology keeps track of the depths and stream positions for all events.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue