atagen

matrix-rust-sdk

public
Star0
Watch0
ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk.git

Blame: crates/matrix-sdk-search/src/schema.rs

7ff8adafe9e4atagen2026-10-22 12:30 UTC1
// Copyright 2024 The Matrix.org Foundation C.I.C.
7ff8adafe9e4atagen2026-10-22 12:30 UTC2
//
7ff8adafe9e4atagen2026-10-22 12:30 UTC3
// Licensed under the Apache License, Version 2.0 (the "License");
7ff8adafe9e4atagen2026-10-22 12:30 UTC4
// you may not use this file except in compliance with the License.
7ff8adafe9e4atagen2026-10-22 12:30 UTC5
// You may obtain a copy of the License at
7ff8adafe9e4atagen2026-10-22 12:30 UTC6
//
7ff8adafe9e4atagen2026-10-22 12:30 UTC7
//     http://www.apache.org/licenses/LICENSE-2.0
7ff8adafe9e4atagen2026-10-22 12:30 UTC8
//
7ff8adafe9e4atagen2026-10-22 12:30 UTC9
// Unless required by applicable law or agreed to in writing, software
7ff8adafe9e4atagen2026-10-22 12:30 UTC10
// distributed under the License is distributed on an "AS IS" BASIS,
7ff8adafe9e4atagen2026-10-22 12:30 UTC11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7ff8adafe9e4atagen2026-10-22 12:30 UTC12
// See the License for the specific language governing permissions and
7ff8adafe9e4atagen2026-10-22 12:30 UTC13
// limitations under the License.
7ff8adafe9e4atagen2026-10-22 12:30 UTC14
7ff8adafe9e4atagen2026-10-22 12:30 UTC15
use ruma::events::room::message::{MessageType, OriginalSyncRoomMessageEvent, Relation};
7ff8adafe9e4atagen2026-10-22 12:30 UTC16
use tantivy::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC17
    DateTime, TantivyDocument, doc,
7ff8adafe9e4atagen2026-10-22 12:30 UTC18
    schema::{DateOptions, DateTimePrecision, Field, INDEXED, STORED, STRING, Schema, TEXT},
7ff8adafe9e4atagen2026-10-22 12:30 UTC19
};
7ff8adafe9e4atagen2026-10-22 12:30 UTC20
7ff8adafe9e4atagen2026-10-22 12:30 UTC21
use crate::error::{IndexError, IndexSchemaError};
7ff8adafe9e4atagen2026-10-22 12:30 UTC22
7ff8adafe9e4atagen2026-10-22 12:30 UTC23
pub(crate) trait MatrixSearchIndexSchema {
7ff8adafe9e4atagen2026-10-22 12:30 UTC24
    fn new() -> Self;
7ff8adafe9e4atagen2026-10-22 12:30 UTC25
    fn default_search_fields(&self) -> Vec<Field>;
7ff8adafe9e4atagen2026-10-22 12:30 UTC26
    fn primary_key(&self) -> Field;
7ff8adafe9e4atagen2026-10-22 12:30 UTC27
    fn deletion_key(&self) -> Field;
7ff8adafe9e4atagen2026-10-22 12:30 UTC28
    fn get_field_name(&self, field: Field) -> &str;
7ff8adafe9e4atagen2026-10-22 12:30 UTC29
    fn as_tantivy_schema(&self) -> Schema;
7ff8adafe9e4atagen2026-10-22 12:30 UTC30
    fn make_doc(&self, event: OriginalSyncRoomMessageEvent) -> Result<TantivyDocument, IndexError>;
7ff8adafe9e4atagen2026-10-22 12:30 UTC31
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC32
7ff8adafe9e4atagen2026-10-22 12:30 UTC33
#[derive(Debug, Clone)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC34
pub(crate) struct RoomMessageSchema {
7ff8adafe9e4atagen2026-10-22 12:30 UTC35
    inner: Schema,
7ff8adafe9e4atagen2026-10-22 12:30 UTC36
    /// The event id of this event (primary key).
7ff8adafe9e4atagen2026-10-22 12:30 UTC37
    event_id_field: Field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC38
    /// The event id of the event that this event affects.
7ff8adafe9e4atagen2026-10-22 12:30 UTC39
    /// Used by edits to refer to the event they edited (deletion key).
7ff8adafe9e4atagen2026-10-22 12:30 UTC40
    original_event_id_field: Field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC41
    body_field: Field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC42
    date_field: Field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC43
    sender_field: Field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC44
    default_search_fields: Vec<Field>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC45
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC46
7ff8adafe9e4atagen2026-10-22 12:30 UTC47
impl MatrixSearchIndexSchema for RoomMessageSchema {
7ff8adafe9e4atagen2026-10-22 12:30 UTC48
    fn new() -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC49
        let mut schema = Schema::builder();
7ff8adafe9e4atagen2026-10-22 12:30 UTC50
        let event_id_field = schema.add_text_field("event_id", STORED | STRING);
7ff8adafe9e4atagen2026-10-22 12:30 UTC51
        let original_event_id_field = schema.add_text_field("original_event_id", STRING);
7ff8adafe9e4atagen2026-10-22 12:30 UTC52
        let body_field = schema.add_text_field("body", TEXT);
7ff8adafe9e4atagen2026-10-22 12:30 UTC53
7ff8adafe9e4atagen2026-10-22 12:30 UTC54
        let date_options =
7ff8adafe9e4atagen2026-10-22 12:30 UTC55
            DateOptions::from(INDEXED).set_fast().set_precision(DateTimePrecision::Seconds);
7ff8adafe9e4atagen2026-10-22 12:30 UTC56
7ff8adafe9e4atagen2026-10-22 12:30 UTC57
        let date_field = schema.add_date_field("date", date_options);
7ff8adafe9e4atagen2026-10-22 12:30 UTC58
        let sender_field = schema.add_text_field("sender", STRING);
7ff8adafe9e4atagen2026-10-22 12:30 UTC59
7ff8adafe9e4atagen2026-10-22 12:30 UTC60
        let default_search_fields = vec![body_field];
7ff8adafe9e4atagen2026-10-22 12:30 UTC61
7ff8adafe9e4atagen2026-10-22 12:30 UTC62
        let schema = schema.build();
7ff8adafe9e4atagen2026-10-22 12:30 UTC63
7ff8adafe9e4atagen2026-10-22 12:30 UTC64
        Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC65
            inner: schema,
7ff8adafe9e4atagen2026-10-22 12:30 UTC66
            event_id_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC67
            original_event_id_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC68
            body_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC69
            date_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC70
            sender_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC71
            default_search_fields,
7ff8adafe9e4atagen2026-10-22 12:30 UTC72
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC73
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC74
7ff8adafe9e4atagen2026-10-22 12:30 UTC75
    fn default_search_fields(&self) -> Vec<Field> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC76
        self.default_search_fields.clone()
7ff8adafe9e4atagen2026-10-22 12:30 UTC77
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC78
7ff8adafe9e4atagen2026-10-22 12:30 UTC79
    fn primary_key(&self) -> Field {
7ff8adafe9e4atagen2026-10-22 12:30 UTC80
        self.event_id_field
7ff8adafe9e4atagen2026-10-22 12:30 UTC81
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC82
7ff8adafe9e4atagen2026-10-22 12:30 UTC83
    fn deletion_key(&self) -> Field {
7ff8adafe9e4atagen2026-10-22 12:30 UTC84
        self.original_event_id_field
7ff8adafe9e4atagen2026-10-22 12:30 UTC85
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC86
7ff8adafe9e4atagen2026-10-22 12:30 UTC87
    fn get_field_name(&self, field: Field) -> &str {
7ff8adafe9e4atagen2026-10-22 12:30 UTC88
        self.inner.get_field_name(field)
7ff8adafe9e4atagen2026-10-22 12:30 UTC89
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC90
7ff8adafe9e4atagen2026-10-22 12:30 UTC91
    fn as_tantivy_schema(&self) -> Schema {
7ff8adafe9e4atagen2026-10-22 12:30 UTC92
        self.inner.clone()
7ff8adafe9e4atagen2026-10-22 12:30 UTC93
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC94
7ff8adafe9e4atagen2026-10-22 12:30 UTC95
    /// Given an [`OriginalSyncRoomMessageEvent`] return a
7ff8adafe9e4atagen2026-10-22 12:30 UTC96
    /// [`TantivyDocument`].
7ff8adafe9e4atagen2026-10-22 12:30 UTC97
    fn make_doc(&self, event: OriginalSyncRoomMessageEvent) -> Result<TantivyDocument, IndexError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC98
        let body = match &event.content.msgtype {
7ff8adafe9e4atagen2026-10-22 12:30 UTC99
            MessageType::Text(content) => Ok(content.body.clone()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC100
            _ => Err(IndexError::MessageTypeNotSupported),
7ff8adafe9e4atagen2026-10-22 12:30 UTC101
        }?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC102
7ff8adafe9e4atagen2026-10-22 12:30 UTC103
        let mut document = doc!(
7ff8adafe9e4atagen2026-10-22 12:30 UTC104
            self.event_id_field => event.event_id.to_string(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC105
            self.body_field => body,
7ff8adafe9e4atagen2026-10-22 12:30 UTC106
            self.date_field =>
7ff8adafe9e4atagen2026-10-22 12:30 UTC107
                DateTime::from_timestamp_millis(
7ff8adafe9e4atagen2026-10-22 12:30 UTC108
                    event.origin_server_ts.get().into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC109
            self.sender_field => event.sender.to_string(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC110
        );
7ff8adafe9e4atagen2026-10-22 12:30 UTC111
7ff8adafe9e4atagen2026-10-22 12:30 UTC112
        if let Some(Relation::Replacement(replacement_data)) = &event.content.relates_to {
7ff8adafe9e4atagen2026-10-22 12:30 UTC113
            document.add_text(self.original_event_id_field, replacement_data.event_id.clone());
7ff8adafe9e4atagen2026-10-22 12:30 UTC114
        } else {
7ff8adafe9e4atagen2026-10-22 12:30 UTC115
            document.add_text(self.original_event_id_field, event.event_id);
7ff8adafe9e4atagen2026-10-22 12:30 UTC116
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC117
7ff8adafe9e4atagen2026-10-22 12:30 UTC118
        Ok(document)
7ff8adafe9e4atagen2026-10-22 12:30 UTC119
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC120
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC121
7ff8adafe9e4atagen2026-10-22 12:30 UTC122
impl TryFrom<Schema> for RoomMessageSchema {
7ff8adafe9e4atagen2026-10-22 12:30 UTC123
    type Error = IndexSchemaError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC124
7ff8adafe9e4atagen2026-10-22 12:30 UTC125
    fn try_from(schema: Schema) -> Result<RoomMessageSchema, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC126
        let event_id_field = schema.get_field("event_id")?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC127
        let original_event_id_field = schema.get_field("original_event_id")?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC128
        let body_field = schema.get_field("body")?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC129
        let date_field = schema.get_field("date")?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC130
        let sender_field = schema.get_field("sender")?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC131
7ff8adafe9e4atagen2026-10-22 12:30 UTC132
        let default_search_fields = vec![body_field];
7ff8adafe9e4atagen2026-10-22 12:30 UTC133
7ff8adafe9e4atagen2026-10-22 12:30 UTC134
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC135
            inner: schema,
7ff8adafe9e4atagen2026-10-22 12:30 UTC136
            event_id_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC137
            original_event_id_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC138
            body_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC139
            date_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC140
            sender_field,
7ff8adafe9e4atagen2026-10-22 12:30 UTC141
            default_search_fields,
7ff8adafe9e4atagen2026-10-22 12:30 UTC142
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC143
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC144
}