fix: preserve custom metadata when updating memory (#4495)
This commit is contained in:
@@ -197,7 +197,8 @@ class MongoDB(VectorStoreBase):
|
|||||||
if vector is not None:
|
if vector is not None:
|
||||||
update_fields["embedding"] = vector
|
update_fields["embedding"] = vector
|
||||||
if payload is not None:
|
if payload is not None:
|
||||||
update_fields["payload"] = payload
|
for key, value in payload.items():
|
||||||
|
update_fields[f"payload.{key}"] = value
|
||||||
|
|
||||||
if update_fields:
|
if update_fields:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -203,6 +203,10 @@ def test_delete(mongo_vector_fixture):
|
|||||||
|
|
||||||
|
|
||||||
def test_update(mongo_vector_fixture):
|
def test_update(mongo_vector_fixture):
|
||||||
|
"""
|
||||||
|
Test that update() uses dot notation for payload fields instead of replacing
|
||||||
|
the entire payload document.
|
||||||
|
"""
|
||||||
mongo_vector, mock_collection, _ = mongo_vector_fixture
|
mongo_vector, mock_collection, _ = mongo_vector_fixture
|
||||||
vector_id = "id1"
|
vector_id = "id1"
|
||||||
updated_vector = [0.3] * 1536
|
updated_vector = [0.3] * 1536
|
||||||
@@ -212,11 +216,51 @@ def test_update(mongo_vector_fixture):
|
|||||||
|
|
||||||
mongo_vector.update(vector_id=vector_id, vector=updated_vector, payload=updated_payload)
|
mongo_vector.update(vector_id=vector_id, vector=updated_vector, payload=updated_payload)
|
||||||
|
|
||||||
|
# Should use dot notation (payload.name) instead of full replacement (payload)
|
||||||
mock_collection.update_one.assert_called_once_with(
|
mock_collection.update_one.assert_called_once_with(
|
||||||
{"_id": vector_id}, {"$set": {"embedding": updated_vector, "payload": updated_payload}}
|
{"_id": vector_id}, {"$set": {"embedding": updated_vector, "payload.name": "updated_vector"}}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_payload_only_uses_dot_notation(mongo_vector_fixture):
|
||||||
|
"""
|
||||||
|
Test that updating only the payload uses dot notation for each field,
|
||||||
|
preserving existing metadata fields not included in the update.
|
||||||
|
"""
|
||||||
|
mongo_vector, mock_collection, _ = mongo_vector_fixture
|
||||||
|
|
||||||
|
mock_collection.update_one.return_value = MagicMock(matched_count=1)
|
||||||
|
|
||||||
|
mongo_vector.update(
|
||||||
|
vector_id="id1",
|
||||||
|
payload={"data": "updated text", "hash": "def456", "updated_at": "2025-06-01"},
|
||||||
|
)
|
||||||
|
|
||||||
|
set_arg = mock_collection.update_one.call_args[0][1]["$set"]
|
||||||
|
|
||||||
|
# Only the specified fields should be in $set, using dot notation
|
||||||
|
assert set_arg == {
|
||||||
|
"payload.data": "updated text",
|
||||||
|
"payload.hash": "def456",
|
||||||
|
"payload.updated_at": "2025-06-01",
|
||||||
|
}
|
||||||
|
# "payload" key itself should NOT appear (that would replace the whole document)
|
||||||
|
assert "payload" not in set_arg
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_vector_only_does_not_touch_payload(mongo_vector_fixture):
|
||||||
|
"""Test that updating only the vector does not touch any payload fields."""
|
||||||
|
mongo_vector, mock_collection, _ = mongo_vector_fixture
|
||||||
|
|
||||||
|
mock_collection.update_one.return_value = MagicMock(matched_count=1)
|
||||||
|
|
||||||
|
mongo_vector.update(vector_id="id1", vector=[0.7, 0.8, 0.9])
|
||||||
|
|
||||||
|
set_arg = mock_collection.update_one.call_args[0][1]["$set"]
|
||||||
|
assert set_arg == {"embedding": [0.7, 0.8, 0.9]}
|
||||||
|
assert not any(k.startswith("payload.") for k in set_arg)
|
||||||
|
|
||||||
|
|
||||||
def test_get(mongo_vector_fixture):
|
def test_get(mongo_vector_fixture):
|
||||||
mongo_vector, mock_collection, _ = mongo_vector_fixture
|
mongo_vector, mock_collection, _ = mongo_vector_fixture
|
||||||
vector_id = "id1"
|
vector_id = "id1"
|
||||||
|
|||||||
Reference in New Issue
Block a user