From c553c07463af10bec1547cf916382f8c93328e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=A4=A7=E6=B4=8B?= <714403855@qq.com> Date: Tue, 20 Jan 2026 15:06:49 +0800 Subject: [PATCH 1/6] feat: delete_time && delete_record_id for neo4j,polardb,neo4j_community --- src/memos/graph_dbs/neo4j.py | 9 +++++++++ src/memos/graph_dbs/neo4j_community.py | 9 +++++++++ src/memos/graph_dbs/polardb.py | 4 ++++ 3 files changed, 22 insertions(+) diff --git a/src/memos/graph_dbs/neo4j.py b/src/memos/graph_dbs/neo4j.py index 8698b6f73..9d514fb23 100644 --- a/src/memos/graph_dbs/neo4j.py +++ b/src/memos/graph_dbs/neo4j.py @@ -209,6 +209,10 @@ def add_node( # Flatten info fields to top level (for Neo4j flat structure) metadata = _flatten_info_fields(metadata) + # Initialize delete_time and delete_record_id fields + metadata.setdefault("delete_time", "") + metadata.setdefault("delete_record_id", "") + # Merge node and set metadata created_at = metadata.pop("created_at") updated_at = metadata.pop("updated_at") @@ -251,6 +255,7 @@ def add_nodes_batch( - metadata: dict[str, Any] - Node metadata user_name: Optional user name (will use config default if not provided) """ + print("a1111dd_nodes_batch") if not nodes: logger.warning("[add_nodes_batch] Empty nodes list, skipping") return @@ -280,6 +285,10 @@ def add_nodes_batch( # Flatten info fields to top level (for Neo4j flat structure) metadata = _flatten_info_fields(metadata) + # Initialize delete_time and delete_record_id fields + metadata.setdefault("delete_time", "") + metadata.setdefault("delete_record_id", "") + # Merge node and set metadata created_at = metadata.pop("created_at") updated_at = metadata.pop("updated_at") diff --git a/src/memos/graph_dbs/neo4j_community.py b/src/memos/graph_dbs/neo4j_community.py index f0be3d858..f2182f6cd 100644 --- a/src/memos/graph_dbs/neo4j_community.py +++ b/src/memos/graph_dbs/neo4j_community.py @@ -56,6 +56,10 @@ def add_node( # Safely process metadata metadata = _prepare_node_metadata(metadata) + # Initialize delete_time and delete_record_id fields + metadata.setdefault("delete_time", "") + metadata.setdefault("delete_record_id", "") + # serialization if metadata["sources"]: for idx in range(len(metadata["sources"])): @@ -105,6 +109,7 @@ def add_node( ) def add_nodes_batch(self, nodes: list[dict[str, Any]], user_name: str | None = None) -> None: + print("neo4j_community add_nodes_batch:") if not nodes: logger.warning("[add_nodes_batch] Empty nodes list, skipping") return @@ -130,6 +135,10 @@ def add_nodes_batch(self, nodes: list[dict[str, Any]], user_name: str | None = N metadata = _prepare_node_metadata(metadata) metadata = _flatten_info_fields(metadata) + # Initialize delete_time and delete_record_id fields + metadata.setdefault("delete_time", "") + metadata.setdefault("delete_record_id", "") + embedding = metadata.pop("embedding", None) if embedding is None: raise ValueError(f"Missing 'embedding' in metadata for node {node_id}") diff --git a/src/memos/graph_dbs/polardb.py b/src/memos/graph_dbs/polardb.py index 4b739bb0f..6c36052cb 100644 --- a/src/memos/graph_dbs/polardb.py +++ b/src/memos/graph_dbs/polardb.py @@ -3394,6 +3394,8 @@ def add_node( "memory": memory, "created_at": created_at, "updated_at": updated_at, + "delete_time": "", + "delete_record_id": "", **metadata, } @@ -3535,6 +3537,8 @@ def add_nodes_batch( "memory": memory, "created_at": created_at, "updated_at": updated_at, + "delete_time": "", + "delete_record_id": "", **metadata, } From 5b4e6ed49c96f01bfa83daf4ad6a82763a562567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=A4=A7=E6=B4=8B?= <714403855@qq.com> Date: Tue, 20 Jan 2026 16:39:53 +0800 Subject: [PATCH 2/6] feat: add log --- src/memos/graph_dbs/polardb.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/memos/graph_dbs/polardb.py b/src/memos/graph_dbs/polardb.py index 6c36052cb..6cb856c10 100644 --- a/src/memos/graph_dbs/polardb.py +++ b/src/memos/graph_dbs/polardb.py @@ -835,6 +835,10 @@ def create_edge(self): def add_edge( self, source_id: str, target_id: str, type: str, user_name: str | None = None ) -> None: + logger.info( + f"polardb [add_edge] source_id: {source_id}, target_id: {target_id}, type: {type},user_name:{user_name}") + + start_time = time.time() if not source_id or not target_id: logger.warning(f"Edge '{source_id}' and '{target_id}' are both None") raise ValueError("[add_edge] source_id and target_id must be provided") @@ -864,13 +868,18 @@ def add_edge( AND end_id = ag_catalog._make_graph_id('{self.db_name}_graph'::name, 'Memory'::name, '{target_id}'::text::cstring) ); """ - + logger.info(f"polardb [add_edge] query: {query}, properties: {json.dumps(properties)}") conn = None try: conn = self._get_connection() with conn.cursor() as cursor: cursor.execute(query, (source_id, target_id, type, json.dumps(properties))) logger.info(f"Edge created: {source_id} -[{type}]-> {target_id}") + + elapsed_time = time.time() - start_time + logger.info( + f" polardb [add_edge] insert completed time in {elapsed_time:.2f}s" + ) except Exception as e: logger.error(f"Failed to insert edge: {e}", exc_info=True) raise @@ -1033,7 +1042,9 @@ def get_node( Returns: dict: Node properties as key-value pairs, or None if not found. """ - + logger.info( + f"polardb [get_node] id: {id}, include_embedding: {include_embedding}, user_name: {user_name}") + start_time = time.time() select_fields = "id, properties, embedding" if include_embedding else "id, properties" query = f""" @@ -1048,6 +1059,7 @@ def get_node( query += "\nAND ag_catalog.agtype_access_operator(properties, '\"user_name\"'::agtype) = %s::agtype" params.append(self.format_param_value(user_name)) + logger.info(f"polardb [get_node] query: {query},params: {params}") conn = None try: conn = self._get_connection() @@ -1084,6 +1096,10 @@ def get_node( except (json.JSONDecodeError, TypeError): logger.warning(f"Failed to parse embedding for node {id}") + elapsed_time = time.time() - start_time + logger.info( + f" polardb [get_node] get_node completed time in {elapsed_time:.2f}s" + ) return self._parse_node( { "id": id, From 5de45a020bbfdb5634021a69eee6fe50fece0c6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=A4=A7=E6=B4=8B?= <714403855@qq.com> Date: Wed, 21 Jan 2026 10:52:57 +0800 Subject: [PATCH 3/6] feat: add search_by_fulltext log --- src/memos/graph_dbs/polardb.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/memos/graph_dbs/polardb.py b/src/memos/graph_dbs/polardb.py index 6cb856c10..056ed7a96 100644 --- a/src/memos/graph_dbs/polardb.py +++ b/src/memos/graph_dbs/polardb.py @@ -1895,7 +1895,7 @@ def search_by_fulltext( filter: dict | None = None, knowledgebase_ids: list[str] | None = None, tsvector_field: str = "properties_tsvector_zh", - tsquery_config: str = "jiebaqry", + tsquery_config: str = "jiebacfg", **kwargs, ) -> list[dict]: """ @@ -1918,7 +1918,10 @@ def search_by_fulltext( Returns: list[dict]: result list containing id and score """ + logger.info( + f"[search_by_fulltext] query_words: {query_words},top_k:{top_k},scope:{scope},status:{status},threshold:{threshold},search_filter:{search_filter},user_name:{user_name},knowledgebase_ids:{knowledgebase_ids},filter:{filter}") # Build WHERE clause dynamically, same as search_by_embedding + start_time = time.time() where_clauses = [] if scope: @@ -1940,6 +1943,7 @@ def search_by_fulltext( knowledgebase_ids=knowledgebase_ids, default_user_name=self.config.user_name, ) + logger.info(f"[search_by_fulltext] user_name_conditions: {user_name_conditions}") # Add OR condition if we have any user_name conditions if user_name_conditions: @@ -1962,6 +1966,8 @@ def search_by_fulltext( # Build filter conditions using common method filter_conditions = self._build_filter_conditions_sql(filter) + logger.info(f"[search_by_fulltext] filter_conditions: {filter_conditions}") + where_clauses.extend(filter_conditions) # Add fulltext search condition # Convert query_text to OR query format: "word1 | word2 | word3" @@ -1971,6 +1977,8 @@ def search_by_fulltext( where_clause = f"WHERE {' AND '.join(where_clauses)}" if where_clauses else "" + logger.info(f"[search_by_fulltext] where_clause: {where_clause}") + # Build fulltext search query query = f""" SELECT @@ -2002,7 +2010,10 @@ def search_by_fulltext( # Apply threshold filter if specified if threshold is None or score_val >= threshold: output.append({"id": id_val, "score": score_val}) - + elapsed_time = time.time() - start_time + logger.info( + f" polardb [search_by_fulltext] query completed time in {elapsed_time:.2f}s" + ) return output[:top_k] finally: self._return_connection(conn) @@ -4301,7 +4312,7 @@ def _build_user_name_and_kb_ids_conditions_sql( user_name_conditions = [] effective_user_name = user_name if user_name else default_user_name - if effective_user_name: + if effective_user_name and default_user_name != 'xxx': user_name_conditions.append( f"ag_catalog.agtype_access_operator(properties, '\"user_name\"'::agtype) = '\"{effective_user_name}\"'::agtype" ) From e7b7c3b80067d285bad0318ff79e495abc1dea58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=A4=A7=E6=B4=8B?= <714403855@qq.com> Date: Thu, 22 Jan 2026 09:21:25 +0800 Subject: [PATCH 4/6] feat: remove --- src/memos/graph_dbs/neo4j.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/memos/graph_dbs/neo4j.py b/src/memos/graph_dbs/neo4j.py index 9d514fb23..fabde06c9 100644 --- a/src/memos/graph_dbs/neo4j.py +++ b/src/memos/graph_dbs/neo4j.py @@ -255,7 +255,6 @@ def add_nodes_batch( - metadata: dict[str, Any] - Node metadata user_name: Optional user name (will use config default if not provided) """ - print("a1111dd_nodes_batch") if not nodes: logger.warning("[add_nodes_batch] Empty nodes list, skipping") return From b876d45301c2994bf3ce864176e0e26bc1da576d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=A4=A7=E6=B4=8B?= <714403855@qq.com> Date: Thu, 22 Jan 2026 09:35:25 +0800 Subject: [PATCH 5/6] feat: add log --- src/memos/graph_dbs/neo4j.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/memos/graph_dbs/neo4j.py b/src/memos/graph_dbs/neo4j.py index fabde06c9..8630c15c3 100644 --- a/src/memos/graph_dbs/neo4j.py +++ b/src/memos/graph_dbs/neo4j.py @@ -255,6 +255,7 @@ def add_nodes_batch( - metadata: dict[str, Any] - Node metadata user_name: Optional user name (will use config default if not provided) """ + logger.info(f"neo4j [add_nodes_batch] staring") if not nodes: logger.warning("[add_nodes_batch] Empty nodes list, skipping") return From 435336241b73e3fe7bd802f455f07ab89b2ae7b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=A4=A7=E6=B4=8B?= <714403855@qq.com> Date: Thu, 22 Jan 2026 09:54:45 +0800 Subject: [PATCH 6/6] feat: fix log --- src/memos/graph_dbs/neo4j.py | 2 +- src/memos/graph_dbs/polardb.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/memos/graph_dbs/neo4j.py b/src/memos/graph_dbs/neo4j.py index 8630c15c3..1c3a4b075 100644 --- a/src/memos/graph_dbs/neo4j.py +++ b/src/memos/graph_dbs/neo4j.py @@ -255,7 +255,7 @@ def add_nodes_batch( - metadata: dict[str, Any] - Node metadata user_name: Optional user name (will use config default if not provided) """ - logger.info(f"neo4j [add_nodes_batch] staring") + logger.info("neo4j [add_nodes_batch] staring") if not nodes: logger.warning("[add_nodes_batch] Empty nodes list, skipping") return diff --git a/src/memos/graph_dbs/polardb.py b/src/memos/graph_dbs/polardb.py index 056ed7a96..40c0c9684 100644 --- a/src/memos/graph_dbs/polardb.py +++ b/src/memos/graph_dbs/polardb.py @@ -836,7 +836,8 @@ def add_edge( self, source_id: str, target_id: str, type: str, user_name: str | None = None ) -> None: logger.info( - f"polardb [add_edge] source_id: {source_id}, target_id: {target_id}, type: {type},user_name:{user_name}") + f"polardb [add_edge] source_id: {source_id}, target_id: {target_id}, type: {type},user_name:{user_name}" + ) start_time = time.time() if not source_id or not target_id: @@ -877,9 +878,7 @@ def add_edge( logger.info(f"Edge created: {source_id} -[{type}]-> {target_id}") elapsed_time = time.time() - start_time - logger.info( - f" polardb [add_edge] insert completed time in {elapsed_time:.2f}s" - ) + logger.info(f" polardb [add_edge] insert completed time in {elapsed_time:.2f}s") except Exception as e: logger.error(f"Failed to insert edge: {e}", exc_info=True) raise @@ -1043,7 +1042,8 @@ def get_node( dict: Node properties as key-value pairs, or None if not found. """ logger.info( - f"polardb [get_node] id: {id}, include_embedding: {include_embedding}, user_name: {user_name}") + f"polardb [get_node] id: {id}, include_embedding: {include_embedding}, user_name: {user_name}" + ) start_time = time.time() select_fields = "id, properties, embedding" if include_embedding else "id, properties" @@ -1919,7 +1919,8 @@ def search_by_fulltext( list[dict]: result list containing id and score """ logger.info( - f"[search_by_fulltext] query_words: {query_words},top_k:{top_k},scope:{scope},status:{status},threshold:{threshold},search_filter:{search_filter},user_name:{user_name},knowledgebase_ids:{knowledgebase_ids},filter:{filter}") + f"[search_by_fulltext] query_words: {query_words},top_k:{top_k},scope:{scope},status:{status},threshold:{threshold},search_filter:{search_filter},user_name:{user_name},knowledgebase_ids:{knowledgebase_ids},filter:{filter}" + ) # Build WHERE clause dynamically, same as search_by_embedding start_time = time.time() where_clauses = [] @@ -4312,7 +4313,7 @@ def _build_user_name_and_kb_ids_conditions_sql( user_name_conditions = [] effective_user_name = user_name if user_name else default_user_name - if effective_user_name and default_user_name != 'xxx': + if effective_user_name and default_user_name != "xxx": user_name_conditions.append( f"ag_catalog.agtype_access_operator(properties, '\"user_name\"'::agtype) = '\"{effective_user_name}\"'::agtype" )