@@ -608,6 +608,132 @@ async def delete_all_documents_async(self, recreate_index: bool = False) -> None
608608 msg = f"Failed to delete all documents from OpenSearch: { e !s} "
609609 raise DocumentStoreError (msg ) from e
610610
611+ def delete_by_filter (self , filters : Dict [str , Any ]) -> int :
612+ """
613+ Deletes all documents that match the provided filters.
614+
615+ :param filters: The filters to apply to select documents for deletion.
616+ For filter syntax, see [Haystack metadata filtering](https://docs.haystack.deepset.ai/docs/metadata-filtering)
617+ :returns: The number of documents deleted.
618+ """
619+ self ._ensure_initialized ()
620+ assert self ._client is not None
621+
622+ try :
623+ normalized_filters = normalize_filters (filters )
624+ body = {"query" : {"bool" : {"filter" : normalized_filters }}}
625+ result = self ._client .delete_by_query (index = self ._index , body = body )
626+ deleted_count = result .get ("deleted" , 0 )
627+ logger .info (
628+ "Deleted {n_docs} documents from index '{index}' using filters." ,
629+ n_docs = deleted_count ,
630+ index = self ._index ,
631+ )
632+ return deleted_count
633+ except Exception as e :
634+ msg = f"Failed to delete documents by filter from OpenSearch: { e !s} "
635+ raise DocumentStoreError (msg ) from e
636+
637+ async def delete_by_filter_async (self , filters : Dict [str , Any ]) -> int :
638+ """
639+ Asynchronously deletes all documents that match the provided filters.
640+
641+ :param filters: The filters to apply to select documents for deletion.
642+ For filter syntax, see [Haystack metadata filtering](https://docs.haystack.deepset.ai/docs/metadata-filtering)
643+ :returns: The number of documents deleted.
644+ """
645+ self ._ensure_initialized ()
646+ assert self ._async_client is not None
647+
648+ try :
649+ normalized_filters = normalize_filters (filters )
650+ body = {"query" : {"bool" : {"filter" : normalized_filters }}}
651+ result = await self ._async_client .delete_by_query (index = self ._index , body = body )
652+ deleted_count = result .get ("deleted" , 0 )
653+ logger .info (
654+ "Deleted {n_docs} documents from index '{index}' using filters." ,
655+ n_docs = deleted_count ,
656+ index = self ._index ,
657+ )
658+ return deleted_count
659+ except Exception as e :
660+ msg = f"Failed to delete documents by filter from OpenSearch: { e !s} "
661+ raise DocumentStoreError (msg ) from e
662+
663+ def update_by_filter (self , filters : Dict [str , Any ], meta : Dict [str , Any ]) -> int :
664+ """
665+ Updates the metadata of all documents that match the provided filters.
666+
667+ :param filters: The filters to apply to select documents for updating.
668+ For filter syntax, see [Haystack metadata filtering](https://docs.haystack.deepset.ai/docs/metadata-filtering)
669+ :param meta: The metadata fields to update.
670+ :returns: The number of documents updated.
671+ """
672+ self ._ensure_initialized ()
673+ assert self ._client is not None
674+
675+ try :
676+ normalized_filters = normalize_filters (filters )
677+ # Build the update script to modify metadata fields
678+ # Documents are stored with flattened metadata, so update fields directly in ctx._source
679+ update_script_lines = []
680+ for key in meta .keys ():
681+ update_script_lines .append (f"ctx._source.{ key } = params.{ key } ;" )
682+ update_script = " " .join (update_script_lines )
683+
684+ body = {
685+ "query" : {"bool" : {"filter" : normalized_filters }},
686+ "script" : {"source" : update_script , "params" : meta , "lang" : "painless" },
687+ }
688+ result = self ._client .update_by_query (index = self ._index , body = body )
689+ updated_count = result .get ("updated" , 0 )
690+ logger .info (
691+ "Updated {n_docs} documents in index '{index}' using filters." ,
692+ n_docs = updated_count ,
693+ index = self ._index ,
694+ )
695+ return updated_count
696+ except Exception as e :
697+ msg = f"Failed to update documents by filter in OpenSearch: { e !s} "
698+ raise DocumentStoreError (msg ) from e
699+
700+ async def update_by_filter_async (self , filters : Dict [str , Any ], meta : Dict [str , Any ]) -> int :
701+ """
702+ Asynchronously updates the metadata of all documents that match the provided filters.
703+
704+ :param filters: The filters to apply to select documents for updating.
705+ For filter syntax, see [Haystack metadata filtering](https://docs.haystack.deepset.ai/docs/metadata-filtering)
706+ :param meta: The metadata fields to update.
707+ :returns: The number of documents updated.
708+ """
709+ self ._ensure_initialized ()
710+ assert self ._async_client is not None
711+
712+ try :
713+ normalized_filters = normalize_filters (filters )
714+ # Build the update script to modify metadata fields
715+ # Documents are stored with flattened metadata, so update fields directly in ctx._source
716+ update_script_lines = []
717+ for key in meta .keys ():
718+ update_script_lines .append (f"ctx._source.{ key } = params.{ key } ;" )
719+ update_script = " " .join (update_script_lines )
720+
721+ body = {
722+ "query" : {"bool" : {"filter" : normalized_filters }},
723+ "script" : {"source" : update_script , "params" : meta , "lang" : "painless" },
724+ }
725+ result = await self ._async_client .update_by_query (index = self ._index , body = body )
726+ updated_count = result .get ("updated" , 0 )
727+ logger .info (
728+ "Updated {n_docs} documents in index '{index}' using filters." ,
729+ n_docs = updated_count ,
730+ index = self ._index ,
731+ )
732+ return updated_count
733+ except Exception as e :
734+ msg = f"Failed to update documents by filter in OpenSearch: { e !s} "
735+ raise DocumentStoreError (msg ) from e
736+
611737 def _prepare_bm25_search_request (
612738 self ,
613739 * ,
0 commit comments