Skip to content

Order MongoDB chat memory by message sequence - #6720

Open
MacAlsandair wants to merge 1 commit into
spring-projects:mainfrom
MacAlsandair:mongo-chat-memory-ordering
Open

Order MongoDB chat memory by message sequence#6720
MacAlsandair wants to merge 1 commit into
spring-projects:mainfrom
MacAlsandair:mongo-chat-memory-ordering

Conversation

@MacAlsandair

Copy link
Copy Markdown

MongoChatMemoryRepository orders a conversation by its timestamp field alone. MongoDB stores java.time.Instant as a BSON date with millisecond precision, and saveAll() writes the whole conversation in a single batch, so all of its messages end up with the same timestamp.

Sorting on duplicate keys has no defined order. From the manual: "When sorting on a field which contains duplicate values, documents containing those values may be returned in any order [...] If consistent sort order is desired, include at least one field in your sort that contains unique values." So a conversation can come back with its turns out of order, and since every save rewrites the whole conversation, a bad read is written straight back.

Checked against mongo:8.0.6 by replaying the current write path with 20 messages: 20 distinct Instants go in, differing in nanoseconds, and 1 distinct value comes back out, on every run.

Every other repository keeps an explicit ordering key — JDBC sequence_id, Neo4j idx, Redis a counter, Cassandra a native list. This adds the same for MongoDB: each document stores its position in a sequence field, and reads sort on it. The equivalent problem was fixed for JDBC in #4740.

Existing data is unaffected. sequence is nullable and timestamp remains the secondary sort key, so documents written by earlier versions all tie on sequence and keep the exact ordering they had; they get real sequence numbers on their next save. No migration is required, and the upgrade notes cover an optional backfill.

The auto-configured main index becomes conversationId, sequence, timestamp so the sort stays index-covered.

Verified with MongoChatMemoryRepositoryIT (13 tests) and MongoChatMemoryAutoConfigurationIT (2 tests), including one that reads raw pre-upgrade documents to pin the compatibility behaviour.

Ordering relied on the timestamp field alone. MongoDB stores Instant
with millisecond precision and saveAll() writes the whole conversation
in one batch, so all of its messages get the same timestamp, and a sort
on duplicate keys has no defined order.

Store each message's position in a sequence field and sort on that, as
JdbcChatMemoryRepository does. The field is nullable and timestamp
remains the secondary key, so documents written earlier keep the order
they had and need no migration.

See spring-projects#4740

Signed-off-by: Alexander Makarov <alexander.makarov@nightsong.li>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants