github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/shard_write_inverted_lsm_delete.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package db
    13  
    14  import (
    15  	"encoding/binary"
    16  	"fmt"
    17  
    18  	"github.com/pkg/errors"
    19  	"github.com/weaviate/weaviate/adapters/repos/db/helpers"
    20  	"github.com/weaviate/weaviate/adapters/repos/db/inverted"
    21  	"github.com/weaviate/weaviate/adapters/repos/db/lsmkv"
    22  )
    23  
    24  func (s *Shard) deleteFromInvertedIndicesLSM(props []inverted.Property, nilProps []inverted.NilProperty,
    25  	docID uint64,
    26  ) error {
    27  	for _, prop := range props {
    28  		if prop.HasFilterableIndex {
    29  			bucket := s.store.Bucket(helpers.BucketFromPropNameLSM(prop.Name))
    30  			if bucket == nil {
    31  				return fmt.Errorf("no bucket for prop '%s' found", prop.Name)
    32  			}
    33  
    34  			for _, item := range prop.Items {
    35  				if err := s.deleteFromPropertySetBucket(bucket, docID, item.Data); err != nil {
    36  					return errors.Wrapf(err, "delete item '%s' from index",
    37  						string(item.Data))
    38  				}
    39  			}
    40  		}
    41  
    42  		if prop.HasSearchableIndex {
    43  			bucket := s.store.Bucket(helpers.BucketSearchableFromPropNameLSM(prop.Name))
    44  			if bucket == nil {
    45  				return fmt.Errorf("no bucket searchable for prop '%s' found", prop.Name)
    46  			}
    47  
    48  			for _, item := range prop.Items {
    49  				if err := s.deleteInvertedIndexItemWithFrequencyLSM(bucket, item,
    50  					docID); err != nil {
    51  					return errors.Wrapf(err, "delete item '%s' from index",
    52  						string(item.Data))
    53  				}
    54  			}
    55  		}
    56  
    57  		// add non-nil properties to the null-state inverted index, but skip internal properties (__meta_count, _id etc)
    58  		if isMetaCountProperty(prop) || isInternalProperty(prop) {
    59  			continue
    60  		}
    61  
    62  		// properties where defining a length does not make sense (floats etc.) have a negative entry as length
    63  		if s.index.invertedIndexConfig.IndexPropertyLength && prop.Length >= 0 {
    64  			if err := s.deleteFromPropertyLengthIndex(prop.Name, docID, prop.Length); err != nil {
    65  				return errors.Wrap(err, "add indexed property length")
    66  			}
    67  		}
    68  
    69  		if s.index.invertedIndexConfig.IndexNullState {
    70  			if err := s.deleteFromPropertyNullIndex(prop.Name, docID, prop.Length == 0); err != nil {
    71  				return errors.Wrap(err, "add indexed null state")
    72  			}
    73  		}
    74  	}
    75  
    76  	// remove nil properties from the nullstate and property length inverted index
    77  	for _, nilProperty := range nilProps {
    78  		if s.index.invertedIndexConfig.IndexPropertyLength && nilProperty.AddToPropertyLength {
    79  			if err := s.deleteFromPropertyLengthIndex(nilProperty.Name, docID, 0); err != nil {
    80  				return errors.Wrap(err, "add indexed property length")
    81  			}
    82  		}
    83  
    84  		if s.index.invertedIndexConfig.IndexNullState {
    85  			if err := s.deleteFromPropertyNullIndex(nilProperty.Name, docID, true); err != nil {
    86  				return errors.Wrap(err, "add indexed null state")
    87  			}
    88  		}
    89  	}
    90  
    91  	return nil
    92  }
    93  
    94  func (s *Shard) deleteInvertedIndexItemWithFrequencyLSM(bucket *lsmkv.Bucket,
    95  	item inverted.Countable, docID uint64,
    96  ) error {
    97  	lsmkv.CheckExpectedStrategy(bucket.Strategy(), lsmkv.StrategyMapCollection)
    98  
    99  	docIDBytes := make([]byte, 8)
   100  	// Shard Index version 2 requires BigEndian for sorting, if the shard was
   101  	// built prior assume it uses LittleEndian
   102  	if s.versioner.Version() < 2 {
   103  		binary.LittleEndian.PutUint64(docIDBytes, docID)
   104  	} else {
   105  		binary.BigEndian.PutUint64(docIDBytes, docID)
   106  	}
   107  
   108  	return bucket.MapDeleteKey(item.Data, docIDBytes)
   109  }
   110  
   111  func (s *Shard) deleteFromPropertyLengthIndex(propName string, docID uint64, length int) error {
   112  	bucketLength := s.store.Bucket(helpers.BucketFromPropNameLengthLSM(propName))
   113  	if bucketLength == nil {
   114  		return errors.Errorf("no bucket for prop '%s' length found", propName)
   115  	}
   116  
   117  	key, err := bucketKeyPropertyLength(length)
   118  	if err != nil {
   119  		return errors.Wrapf(err, "failed creating key for prop '%s' length", propName)
   120  	}
   121  	if err := s.deleteFromPropertySetBucket(bucketLength, docID, key); err != nil {
   122  		return errors.Wrapf(err, "failed adding to prop '%s' length bucket", propName)
   123  	}
   124  	return nil
   125  }
   126  
   127  func (s *Shard) deleteFromPropertyNullIndex(propName string, docID uint64, isNull bool) error {
   128  	bucketNull := s.store.Bucket(helpers.BucketFromPropNameNullLSM(propName))
   129  	if bucketNull == nil {
   130  		return errors.Errorf("no bucket for prop '%s' null found", propName)
   131  	}
   132  
   133  	key, err := bucketKeyPropertyNull(isNull)
   134  	if err != nil {
   135  		return errors.Wrapf(err, "failed creating key for prop '%s' null", propName)
   136  	}
   137  	if err := s.deleteFromPropertySetBucket(bucketNull, docID, key); err != nil {
   138  		return errors.Wrapf(err, "failed adding to prop '%s' null bucket", propName)
   139  	}
   140  	return nil
   141  }
   142  
   143  func (s *Shard) deleteFromPropertySetBucket(bucket *lsmkv.Bucket, docID uint64, key []byte) error {
   144  	lsmkv.CheckExpectedStrategy(bucket.Strategy(), lsmkv.StrategySetCollection, lsmkv.StrategyRoaringSet)
   145  
   146  	if bucket.Strategy() == lsmkv.StrategySetCollection {
   147  		docIDBytes := make([]byte, 8)
   148  		binary.LittleEndian.PutUint64(docIDBytes, docID)
   149  
   150  		return bucket.SetDeleteSingle(key, docIDBytes)
   151  	}
   152  
   153  	return bucket.RoaringSetRemoveOne(key, docID)
   154  }