2020 ScopeAlreadyExistsException ,
2121)
2222from couchbase .management .buckets import CreateBucketSettings
23- from couchbase .management .collections import CollectionSpec
2423from couchbase .management .options import CreatePrimaryQueryIndexOptions
2524from couchbase .options import ClusterOptions
25+ from couchbase .subdocument import upsert
2626from opentelemetry .trace import get_tracer
2727
2828from cbltest .api .error import CblTestError
@@ -87,7 +87,7 @@ def create_collections(self, bucket: str, scope: str, names: list[str]) -> None:
8787 ):
8888 try :
8989 if name != "_default" :
90- c .create_collection (CollectionSpec ( name , scope ) )
90+ c .create_collection (scope_name = scope , collection_name = name )
9191 except CollectionAlreadyExistsException :
9292 pass
9393
@@ -294,6 +294,151 @@ def upsert_document(
294294 f"Failed to insert document '{ doc_id } ' into { bucket } .{ scope } .{ collection } : { e } "
295295 )
296296
297+ def delete_document (
298+ self ,
299+ bucket : str ,
300+ doc_id : str ,
301+ scope : str = "_default" ,
302+ collection : str = "_default" ,
303+ ) -> None :
304+ """
305+ Deletes a document from the specified bucket.scope.collection.
306+ """
307+ with self .__tracer .start_as_current_span (
308+ "delete_document" ,
309+ attributes = {
310+ "cbl.bucket.name" : bucket ,
311+ "cbl.scope.name" : scope ,
312+ "cbl.collection.name" : collection ,
313+ "cbl.document.id" : doc_id ,
314+ },
315+ ):
316+ try :
317+ bucket_obj = _try_n_times (10 , 1 , False , self .__cluster .bucket , bucket )
318+ coll = bucket_obj .scope (scope ).collection (collection )
319+ coll .remove (doc_id )
320+ except DocumentNotFoundException :
321+ pass
322+ except Exception as e :
323+ raise CblTestError (
324+ f"Failed to delete document '{ doc_id } ' from { bucket } .{ scope } .{ collection } : { e } "
325+ )
326+
327+ def get_document (
328+ self ,
329+ bucket : str ,
330+ doc_id : str ,
331+ scope : str = "_default" ,
332+ collection : str = "_default" ,
333+ ) -> dict | None :
334+ """
335+ Gets a document from the specified bucket.scope.collection.
336+
337+ :param bucket: The bucket name.
338+ :param doc_id: The document ID.
339+ :param scope: The scope name.
340+ :param collection: The collection name.
341+ :return: The document content as a dictionary, or None if not found.
342+ """
343+ with self .__tracer .start_as_current_span (
344+ "get_document" ,
345+ attributes = {
346+ "cbl.bucket.name" : bucket ,
347+ "cbl.scope.name" : scope ,
348+ "cbl.collection.name" : collection ,
349+ "cbl.document.id" : doc_id ,
350+ },
351+ ):
352+ try :
353+ bucket_obj = _try_n_times (10 , 1 , False , self .__cluster .bucket , bucket )
354+ coll = bucket_obj .scope (scope ).collection (collection )
355+ result = coll .get (doc_id )
356+ return result .content_as [dict ] if result else None
357+ except DocumentNotFoundException :
358+ return None
359+ except Exception as e :
360+ raise CblTestError (
361+ f"Failed to get document '{ doc_id } ' from { bucket } .{ scope } .{ collection } : { e } "
362+ )
363+
364+ def upsert_document_xattr (
365+ self ,
366+ bucket : str ,
367+ doc_id : str ,
368+ xattr_key : str ,
369+ xattr_value : str ,
370+ scope : str = "_default" ,
371+ collection : str = "_default" ,
372+ ) -> None :
373+ """
374+ Upserts an xattr on a document using subdocument operations
375+
376+ :param bucket: The bucket containing the document
377+ :param doc_id: The ID of the document to update
378+ :param xattr_key: The xattr key to upsert
379+ :param xattr_value: The value to set for the xattr
380+ :param scope: The scope containing the document (default '_default')
381+ :param collection: The collection containing the document (default '_default')
382+ """
383+ with self .__tracer .start_as_current_span (
384+ "upsert_document_xattr" ,
385+ attributes = {
386+ "cbl.bucket" : bucket ,
387+ "cbl.scope" : scope ,
388+ "cbl.collection" : collection ,
389+ "cbl.document.id" : doc_id ,
390+ "cbl.xattr.key" : xattr_key ,
391+ },
392+ ):
393+ try :
394+ col = self .__cluster .bucket (bucket ).scope (scope ).collection (collection )
395+ col .mutate_in (
396+ doc_id ,
397+ [upsert (xattr_key , xattr_value , xattr = True , create_parents = True )],
398+ )
399+ except Exception as e :
400+ raise CblTestError (
401+ f"Failed to upsert xattr '{ xattr_key } ' on document '{ doc_id } ' in { bucket } .{ scope } .{ collection } : { e } "
402+ )
403+
404+ def delete_document_xattr (
405+ self ,
406+ bucket : str ,
407+ doc_id : str ,
408+ xattr_key : str ,
409+ scope : str = "_default" ,
410+ collection : str = "_default" ,
411+ ) -> None :
412+ """
413+ Deletes an xattr from a document using subdocument operations
414+
415+ :param bucket: The bucket containing the document
416+ :param doc_id: The ID of the document
417+ :param xattr_key: The xattr key to delete
418+ :param scope: The scope containing the document (default '_default')
419+ :param collection: The collection containing the document (default '_default')
420+ """
421+ with self .__tracer .start_as_current_span (
422+ "delete_document_xattr" ,
423+ attributes = {
424+ "cbl.bucket" : bucket ,
425+ "cbl.scope" : scope ,
426+ "cbl.collection" : collection ,
427+ "cbl.document.id" : doc_id ,
428+ "cbl.xattr.key" : xattr_key ,
429+ },
430+ ):
431+ try :
432+ from couchbase .subdocument import remove
433+
434+ col = self .__cluster .bucket (bucket ).scope (scope ).collection (collection )
435+ col .mutate_in (
436+ doc_id ,
437+ [remove (xattr_key , xattr = True )],
438+ )
439+ except Exception :
440+ pass
441+
297442 def start_xdcr (self , target : "CouchbaseServer" , bucket_name : str ) -> None :
298443 """
299444 Starts an XDCR replication from this cluster to the target cluster
@@ -449,4 +594,4 @@ def stop_xcdr(self, target: "CouchbaseServer", bucket_name: str) -> None:
449594 resp = session .delete (
450595 f"http://{ self .__hostname } :8091/controller/cancelXDCR/{ encoded } " ,
451596 )
452- resp .raise_for_status ()
597+ resp .raise_for_status ()
0 commit comments