weaviate_record 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/lib/weaviate_record/base.rb +241 -0
 - data/lib/weaviate_record/concerns/attribute_concern.rb +76 -0
 - data/lib/weaviate_record/concerns/record_concern.rb +80 -0
 - data/lib/weaviate_record/connection.rb +53 -0
 - data/lib/weaviate_record/constants.rb +25 -0
 - data/lib/weaviate_record/errors.rb +69 -0
 - data/lib/weaviate_record/inspect.rb +36 -0
 - data/lib/weaviate_record/method_missing.rb +24 -0
 - data/lib/weaviate_record/queries/ask.rb +30 -0
 - data/lib/weaviate_record/queries/bm25.rb +29 -0
 - data/lib/weaviate_record/queries/count.rb +21 -0
 - data/lib/weaviate_record/queries/limit.rb +21 -0
 - data/lib/weaviate_record/queries/near_object.rb +35 -0
 - data/lib/weaviate_record/queries/near_text.rb +36 -0
 - data/lib/weaviate_record/queries/near_vector.rb +32 -0
 - data/lib/weaviate_record/queries/offset.rb +22 -0
 - data/lib/weaviate_record/queries/order.rb +74 -0
 - data/lib/weaviate_record/queries/select.rb +85 -0
 - data/lib/weaviate_record/queries/where.rb +126 -0
 - data/lib/weaviate_record/relation/query_builder.rb +59 -0
 - data/lib/weaviate_record/relation.rb +86 -0
 - data/lib/weaviate_record/schema.rb +101 -0
 - data/lib/weaviate_record.rb +38 -0
 - metadata +111 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: af84dff0fba26b232fd8b537749ff5742f5bcc0197656cc647e8b6791a55bd85
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 9534adbc21943b257d0e8f0a517721dd17bb93a1d1e3c14f284e11f30499f1f9
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: e7d0fda549172607928d6e943426f5091d481d4cbcd4c44bb767a32ef667769091238125f79926c1070358dc1095a191e52af70d20ea915b17acbf4eeac51beb
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: dde3def3b42f332182c8d7f8cc115a1516f177be5abedbd516713e00474f9c1b7b9935da51ef134d9010b773df8acb95d2f867a4be043765edef53308e97b201
         
     | 
| 
         @@ -0,0 +1,241 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'forwardable'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module WeaviateRecord
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Base class for the models to inherit from and to interact with the respective collection in weaviate.
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Base
         
     | 
| 
      
 8 
     | 
    
         
            +
                extend ActiveModel::Naming
         
     | 
| 
      
 9 
     | 
    
         
            +
                include ActiveModel::Conversion
         
     | 
| 
      
 10 
     | 
    
         
            +
                include ActiveModel::Validations
         
     | 
| 
      
 11 
     | 
    
         
            +
                include Inspect
         
     | 
| 
      
 12 
     | 
    
         
            +
                include MethodMissing
         
     | 
| 
      
 13 
     | 
    
         
            +
                include Concerns::RecordConcern
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 16 
     | 
    
         
            +
                  extend Forwardable
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def_delegators(:relation, :all, :bm25, :limit, :near_text, :near_vector, :near_object,
         
     | 
| 
      
 18 
     | 
    
         
            +
                                 :offset, :order, :select, :where, :ask, :destroy_all, :first, :last)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  # Creates a new weaviate record and saves it and returns the record.
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # Takes a key value pair of attributes that the record should be initialized with.
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # If the record is not saved, it returns the unsaved record object with errors.
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # ==== Example:
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #  Article.create(title: 'Hello World', content: 'This is the content of the article')
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #  # => #<Article:0x0000000105468ab0 id: "8280210b-9372-4e70-a045-beb7c12a9a24" ...>
         
     | 
| 
      
 28 
     | 
    
         
            +
                  def create(**attributes_hash)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    record = new(**attributes_hash)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    record.save
         
     | 
| 
      
 31 
     | 
    
         
            +
                    record
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  # Takes an _uuid_ and returns the record with that _uuid_.
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # If the record is not found, it raises a +RecordNotFoundError+.
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # ==== Example:
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #   Article.find('f3b1b3b1-0b3b-4b3b-8b3b-0b3b3b3b3b3b')
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #   #<Article:0x0000000105468ab0 id: "8280210b-9372-4e70-a045-beb7c12a9a24" ...>
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def find(id)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    result = connection.find_call(id)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    if result.is_a?(Hash) && result['id']
         
     | 
| 
      
 44 
     | 
    
         
            +
                      new(_additional: meta_attributes(result), **result['properties'])
         
     | 
| 
      
 45 
     | 
    
         
            +
                    elsif result == ''
         
     | 
| 
      
 46 
     | 
    
         
            +
                      raise WeaviateRecord::Errors::RecordNotFoundError, "Couldn't find record with id=#{id}"
         
     | 
| 
      
 47 
     | 
    
         
            +
                    else
         
     | 
| 
      
 48 
     | 
    
         
            +
                      raise WeaviateRecord::Errors::ServerError, result['message']
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  # Returns the count of all records in the collection.
         
     | 
| 
      
 53 
     | 
    
         
            +
                  #
         
     | 
| 
      
 54 
     | 
    
         
            +
                  # ==== Example:
         
     | 
| 
      
 55 
     | 
    
         
            +
                  #    class Article < WeaviateRecord::Base
         
     | 
| 
      
 56 
     | 
    
         
            +
                  #    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  #
         
     | 
| 
      
 58 
     | 
    
         
            +
                  #    Article.count # => 0
         
     | 
| 
      
 59 
     | 
    
         
            +
                  #
         
     | 
| 
      
 60 
     | 
    
         
            +
                  #    Article.create(title: 'Hello World', content: 'This is the content of the article')
         
     | 
| 
      
 61 
     | 
    
         
            +
                  #
         
     | 
| 
      
 62 
     | 
    
         
            +
                  #    Article.count # => 1
         
     | 
| 
      
 63 
     | 
    
         
            +
                  def count
         
     | 
| 
      
 64 
     | 
    
         
            +
                    result = connection.client.query.aggs(class_name: to_s, fields: 'meta { count }')
         
     | 
| 
      
 65 
     | 
    
         
            +
                    result.dig(0, 'meta', 'count')
         
     | 
| 
      
 66 
     | 
    
         
            +
                  rescue StandardError
         
     | 
| 
      
 67 
     | 
    
         
            +
                    raise WeaviateRecord::Errors::ServerError, "unable to get the count for #{self} collection."
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  # Takes an _uuid_ and checks whether a record with that id exists or not.
         
     | 
| 
      
 71 
     | 
    
         
            +
                  #
         
     | 
| 
      
 72 
     | 
    
         
            +
                  # ==== Example:
         
     | 
| 
      
 73 
     | 
    
         
            +
                  #   Article.exists?('f3b1b3b1-0b3b-4b3b-8b3b-0b3b3b3b3b3b')  # => true
         
     | 
| 
      
 74 
     | 
    
         
            +
                  #   Article.exists?('random_uuid')  # => false
         
     | 
| 
      
 75 
     | 
    
         
            +
                  def exists?(id)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    connection.check_existence(id)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  private
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  def connection
         
     | 
| 
      
 82 
     | 
    
         
            +
                    @connection ||= Connection.new(self)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  def relation
         
     | 
| 
      
 86 
     | 
    
         
            +
                    WeaviateRecord::Relation.new(self)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  def inherited(klass)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    WeaviateRecord::Schema.find_collection(klass)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    super
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                # Creates a new record with the given attributes.
         
     | 
| 
      
 96 
     | 
    
         
            +
                # The attributes can be passed as a hash or as key value pairs.
         
     | 
| 
      
 97 
     | 
    
         
            +
                # It does not save the record in the weaviate database.
         
     | 
| 
      
 98 
     | 
    
         
            +
                #
         
     | 
| 
      
 99 
     | 
    
         
            +
                #
         
     | 
| 
      
 100 
     | 
    
         
            +
                # ==== Example:
         
     | 
| 
      
 101 
     | 
    
         
            +
                #  Article.new(title: 'Hello World', content: 'This is the content of the article')
         
     | 
| 
      
 102 
     | 
    
         
            +
                #
         
     | 
| 
      
 103 
     | 
    
         
            +
                #  # => #<Article:0x0000000105468ab0 ... "Hello World", content: "This is the content of the article">
         
     | 
| 
      
 104 
     | 
    
         
            +
                #
         
     | 
| 
      
 105 
     | 
    
         
            +
                #  Article.title # => "Hello World"
         
     | 
| 
      
 106 
     | 
    
         
            +
                #  Article.content # => "This is the content of the article"
         
     | 
| 
      
 107 
     | 
    
         
            +
                #
         
     | 
| 
      
 108 
     | 
    
         
            +
                #  Article.title = 'Not Hello World'
         
     | 
| 
      
 109 
     | 
    
         
            +
                #  Article.title # => "Not Hello World"
         
     | 
| 
      
 110 
     | 
    
         
            +
                #
         
     | 
| 
      
 111 
     | 
    
         
            +
                #  Article.persisted? # => false
         
     | 
| 
      
 112 
     | 
    
         
            +
                #
         
     | 
| 
      
 113 
     | 
    
         
            +
                #
         
     | 
| 
      
 114 
     | 
    
         
            +
                # The +custom_selected+ parameter is used to indicate whether the attributes are custom picked.
         
     | 
| 
      
 115 
     | 
    
         
            +
                # If the attributes are custom picked, the attribute readers will be defined only for the selected attributes.
         
     | 
| 
      
 116 
     | 
    
         
            +
                # The record with custom_selected as true cannot be saved, updated, or destroyed.
         
     | 
| 
      
 117 
     | 
    
         
            +
                def initialize(hash = {}, custom_selected: false, **attributes)
         
     | 
| 
      
 118 
     | 
    
         
            +
                  attributes_hash = (hash.present? ? hash : attributes).deep_transform_keys(&:to_s)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  @connection = WeaviateRecord::Connection.new(collection_name)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  @custom_selected = custom_selected
         
     | 
| 
      
 121 
     | 
    
         
            +
                  @attributes = {}
         
     | 
| 
      
 122 
     | 
    
         
            +
                  @meta_attributes = attributes_hash['_additional'] || { 'id' => nil, 'creationTimeUnix' => nil,
         
     | 
| 
      
 123 
     | 
    
         
            +
                                                                         'lastUpdateTimeUnix' => nil }
         
     | 
| 
      
 124 
     | 
    
         
            +
                  run_attribute_handlers(attributes_hash)
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                # Saves the record in the weaviate database.
         
     | 
| 
      
 128 
     | 
    
         
            +
                # Returns true if the record is saved successfully. Otherwise, it returns false.
         
     | 
| 
      
 129 
     | 
    
         
            +
                # If the record is not saved successfully, it adds the errors to the record.
         
     | 
| 
      
 130 
     | 
    
         
            +
                # If the record is already saved, it updates the record.
         
     | 
| 
      
 131 
     | 
    
         
            +
                #
         
     | 
| 
      
 132 
     | 
    
         
            +
                # ==== Example:
         
     | 
| 
      
 133 
     | 
    
         
            +
                #  class Article < WeaviateRecord::Base
         
     | 
| 
      
 134 
     | 
    
         
            +
                #    validates :title, presence: true
         
     | 
| 
      
 135 
     | 
    
         
            +
                #  end
         
     | 
| 
      
 136 
     | 
    
         
            +
                #
         
     | 
| 
      
 137 
     | 
    
         
            +
                #  article = Article.new(title: 'Hello World', content: 'This is the content of the article')
         
     | 
| 
      
 138 
     | 
    
         
            +
                #  article.save # => true
         
     | 
| 
      
 139 
     | 
    
         
            +
                #
         
     | 
| 
      
 140 
     | 
    
         
            +
                #  article.title = 'New title'
         
     | 
| 
      
 141 
     | 
    
         
            +
                #  article.save # => true
         
     | 
| 
      
 142 
     | 
    
         
            +
                #
         
     | 
| 
      
 143 
     | 
    
         
            +
                #  article.title # => "New title"
         
     | 
| 
      
 144 
     | 
    
         
            +
                #
         
     | 
| 
      
 145 
     | 
    
         
            +
                #  article = Article.new(title: '')
         
     | 
| 
      
 146 
     | 
    
         
            +
                #  article.save # => false
         
     | 
| 
      
 147 
     | 
    
         
            +
                #  article.errors.full_messages # => ["Title can't be blank"]
         
     | 
| 
      
 148 
     | 
    
         
            +
                #
         
     | 
| 
      
 149 
     | 
    
         
            +
                def save
         
     | 
| 
      
 150 
     | 
    
         
            +
                  result = validate_and_save
         
     | 
| 
      
 151 
     | 
    
         
            +
                  return false unless result
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                  if result['error'].present?
         
     | 
| 
      
 154 
     | 
    
         
            +
                    errors.add(:base, message: result['error'])
         
     | 
| 
      
 155 
     | 
    
         
            +
                    false
         
     | 
| 
      
 156 
     | 
    
         
            +
                  else
         
     | 
| 
      
 157 
     | 
    
         
            +
                    @meta_attributes.merge!(self.class.meta_attributes(result))
         
     | 
| 
      
 158 
     | 
    
         
            +
                    true
         
     | 
| 
      
 159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 160 
     | 
    
         
            +
                end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                # Updates the record in the weaviate database.
         
     | 
| 
      
 163 
     | 
    
         
            +
                # Returns true if the record is updated successfully. Otherwise, it returns false.
         
     | 
| 
      
 164 
     | 
    
         
            +
                # If the record is not updated successfully, it adds the errors to the record.
         
     | 
| 
      
 165 
     | 
    
         
            +
                #
         
     | 
| 
      
 166 
     | 
    
         
            +
                # ==== Example:
         
     | 
| 
      
 167 
     | 
    
         
            +
                #  class Article < WeaviateRecord::Base
         
     | 
| 
      
 168 
     | 
    
         
            +
                #   validates :title, presence: true
         
     | 
| 
      
 169 
     | 
    
         
            +
                #  end
         
     | 
| 
      
 170 
     | 
    
         
            +
                #
         
     | 
| 
      
 171 
     | 
    
         
            +
                #  article = Article.new(title: 'Hello World', content: 'This is the content of the article')
         
     | 
| 
      
 172 
     | 
    
         
            +
                #  article.save
         
     | 
| 
      
 173 
     | 
    
         
            +
                #
         
     | 
| 
      
 174 
     | 
    
         
            +
                #  article.update(title: 'Not Hello World') # => true
         
     | 
| 
      
 175 
     | 
    
         
            +
                #  article.title # => "Not Hello World"
         
     | 
| 
      
 176 
     | 
    
         
            +
                #
         
     | 
| 
      
 177 
     | 
    
         
            +
                #  article.update(title: '') # => false
         
     | 
| 
      
 178 
     | 
    
         
            +
                #  article.errors.full_messages # => ["Title can't be blank"]
         
     | 
| 
      
 179 
     | 
    
         
            +
                #
         
     | 
| 
      
 180 
     | 
    
         
            +
                # If you try to update the meta attribute, it will raise an error
         
     | 
| 
      
 181 
     | 
    
         
            +
                #
         
     | 
| 
      
 182 
     | 
    
         
            +
                # ==== Example:
         
     | 
| 
      
 183 
     | 
    
         
            +
                #  article.update(id: 'new_id')
         
     | 
| 
      
 184 
     | 
    
         
            +
                #  # => WeaviateRecord::Errors::MetaAttributeError: 'cannot update meta attributes'
         
     | 
| 
      
 185 
     | 
    
         
            +
                def update(hash = {}, **attributes)
         
     | 
| 
      
 186 
     | 
    
         
            +
                  attributes_hash = (hash.present? ? hash : attributes).deep_transform_keys(&:to_s)
         
     | 
| 
      
 187 
     | 
    
         
            +
                  validate_record_for_update(attributes_hash)
         
     | 
| 
      
 188 
     | 
    
         
            +
                  merge_attributes(attributes_hash)
         
     | 
| 
      
 189 
     | 
    
         
            +
                  return false unless valid?
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
                  result = @connection.update_call(@meta_attributes['id'], @attributes)
         
     | 
| 
      
 192 
     | 
    
         
            +
                  raise WeaviateRecord::Errors::ServerError, 'unable to update the weaviate record' unless result.is_a?(Hash)
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                  errors.add(:base, message: result['error']) if result['error'].present?
         
     | 
| 
      
 195 
     | 
    
         
            +
                  result['id'].present?
         
     | 
| 
      
 196 
     | 
    
         
            +
                end
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                # Destroys the record in the weaviate database.
         
     | 
| 
      
 199 
     | 
    
         
            +
                # Returns true if the record is destroyed successfully. Otherwise, it returns false.
         
     | 
| 
      
 200 
     | 
    
         
            +
                # If the record is the original record with valid id, it freezes the existing record object.
         
     | 
| 
      
 201 
     | 
    
         
            +
                # If the record does not have a valid id, it converts all the attributes to nil.
         
     | 
| 
      
 202 
     | 
    
         
            +
                #
         
     | 
| 
      
 203 
     | 
    
         
            +
                # ==== Example:
         
     | 
| 
      
 204 
     | 
    
         
            +
                #  article = Article.new(title: 'Hello World', content: 'This is the content of the article')
         
     | 
| 
      
 205 
     | 
    
         
            +
                #
         
     | 
| 
      
 206 
     | 
    
         
            +
                #  article.destroy # => false
         
     | 
| 
      
 207 
     | 
    
         
            +
                #  article.title   # => nil
         
     | 
| 
      
 208 
     | 
    
         
            +
                #
         
     | 
| 
      
 209 
     | 
    
         
            +
                #  article.title = 'New title'
         
     | 
| 
      
 210 
     | 
    
         
            +
                #  article.save
         
     | 
| 
      
 211 
     | 
    
         
            +
                #
         
     | 
| 
      
 212 
     | 
    
         
            +
                #  article.destroy # => true
         
     | 
| 
      
 213 
     | 
    
         
            +
                #
         
     | 
| 
      
 214 
     | 
    
         
            +
                #  article.frozen? # => true
         
     | 
| 
      
 215 
     | 
    
         
            +
                def destroy
         
     | 
| 
      
 216 
     | 
    
         
            +
                  return self unless validate_record_for_destroy
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                  result = @connection.delete_call(@meta_attributes['id'])
         
     | 
| 
      
 219 
     | 
    
         
            +
                  return freeze if result == true
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
                  errors.add(:base, message: result['error']) if result['error'].present?
         
     | 
| 
      
 222 
     | 
    
         
            +
                  false
         
     | 
| 
      
 223 
     | 
    
         
            +
                end
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
                # Checks whether the record is saved in the weaviate database or not.
         
     | 
| 
      
 226 
     | 
    
         
            +
                # If the record is saved, it returns true. Otherwise, it returns false.
         
     | 
| 
      
 227 
     | 
    
         
            +
                #
         
     | 
| 
      
 228 
     | 
    
         
            +
                # ==== Example:
         
     | 
| 
      
 229 
     | 
    
         
            +
                #  article = Article.new(title: 'Hello World', content: 'This is the content of the article')
         
     | 
| 
      
 230 
     | 
    
         
            +
                #  article.save
         
     | 
| 
      
 231 
     | 
    
         
            +
                #  article.persisted? # => true
         
     | 
| 
      
 232 
     | 
    
         
            +
                def persisted?
         
     | 
| 
      
 233 
     | 
    
         
            +
                  if @custom_selected || !respond_to?(:id)
         
     | 
| 
      
 234 
     | 
    
         
            +
                    raise WeaviateRecord::Errors::CustomQueriedRecordError,
         
     | 
| 
      
 235 
     | 
    
         
            +
                          'cannot perform persisted? action on custom queried record'
         
     | 
| 
      
 236 
     | 
    
         
            +
                  end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                  id.present?
         
     | 
| 
      
 239 
     | 
    
         
            +
                end
         
     | 
| 
      
 240 
     | 
    
         
            +
              end
         
     | 
| 
      
 241 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module WeaviateRecord # :nodoc: all
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Concerns
         
     | 
| 
      
 5 
     | 
    
         
            +
                module AttributeConcern
         
     | 
| 
      
 6 
     | 
    
         
            +
                  private
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def list_of_valid_attributes
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @list_of_valid_attributes ||= WeaviateRecord::Schema.find_collection(collection_name)
         
     | 
| 
      
 10 
     | 
    
         
            +
                                                                        .attributes_list
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def check_attributes(attributes_hash)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    invalid_attributes = attributes_hash.keys - ['_additional', *list_of_valid_attributes]
         
     | 
| 
      
 15 
     | 
    
         
            +
                    return unless invalid_attributes.present?
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    raise WeaviateRecord::Errors::InvalidAttributeError,
         
     | 
| 
      
 18 
     | 
    
         
            +
                          "Invalid attributes #{invalid_attributes} for #{collection_name} record!"
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def merge_attributes(attributes_hash)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    check_attributes(attributes_hash)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    attributes_hash.each do |key, value|
         
     | 
| 
      
 24 
     | 
    
         
            +
                      @attributes[key] = value
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def load_attributes(attributes_hash)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    if attributes_hash.empty? || !@custom_selected
         
     | 
| 
      
 30 
     | 
    
         
            +
                      list_of_valid_attributes.each do |attribute|
         
     | 
| 
      
 31 
     | 
    
         
            +
                        @attributes[attribute] = nil
         
     | 
| 
      
 32 
     | 
    
         
            +
                      end
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    attributes_hash.each do |key, value|
         
     | 
| 
      
 36 
     | 
    
         
            +
                      next if key == '_additional'
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                      @attributes[key] = value
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  def create_attribute_writers
         
     | 
| 
      
 43 
     | 
    
         
            +
                    list_of_valid_attributes.each do |name|
         
     | 
| 
      
 44 
     | 
    
         
            +
                      define_singleton_method("#{name}=") do |value|
         
     | 
| 
      
 45 
     | 
    
         
            +
                        @attributes[name] = value
         
     | 
| 
      
 46 
     | 
    
         
            +
                      end
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  def create_attribute_readers
         
     | 
| 
      
 51 
     | 
    
         
            +
                    attributes_list = @custom_selected ? @attributes.each_key : list_of_valid_attributes
         
     | 
| 
      
 52 
     | 
    
         
            +
                    attributes_list.each do |name|
         
     | 
| 
      
 53 
     | 
    
         
            +
                      define_singleton_method(name) { @attributes[name] }
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    handle_timestamp_attributes
         
     | 
| 
      
 57 
     | 
    
         
            +
                    @meta_attributes.each_key do |name|
         
     | 
| 
      
 58 
     | 
    
         
            +
                      define_singleton_method(name.underscore) { @meta_attributes[name] }
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  def handle_timestamp_attributes
         
     | 
| 
      
 63 
     | 
    
         
            +
                    replace_timestamp_attribute('creationTimeUnix') if @meta_attributes.key? 'creationTimeUnix'
         
     | 
| 
      
 64 
     | 
    
         
            +
                    replace_timestamp_attribute('lastUpdateTimeUnix') if @meta_attributes.key? 'lastUpdateTimeUnix'
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  def replace_timestamp_attribute(attribute)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    mapped_attribute = WeaviateRecord::Constants::SPECIAL_ATTRIBUTE_MAPPINGS.key(attribute)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    @meta_attributes[mapped_attribute] = if @meta_attributes[attribute]
         
     | 
| 
      
 70 
     | 
    
         
            +
                                                           DateTime.strptime(@meta_attributes[attribute], '%Q')
         
     | 
| 
      
 71 
     | 
    
         
            +
                                                         end
         
     | 
| 
      
 72 
     | 
    
         
            +
                    @meta_attributes.delete(attribute)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,80 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module WeaviateRecord # :nodoc: all
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Concerns
         
     | 
| 
      
 5 
     | 
    
         
            +
                module RecordConcern
         
     | 
| 
      
 6 
     | 
    
         
            +
                  extend ActiveSupport::Concern
         
     | 
| 
      
 7 
     | 
    
         
            +
                  include AttributeConcern
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def collection_name
         
     | 
| 
      
 10 
     | 
    
         
            +
                    self.class.to_s
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  private
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def run_attribute_handlers(attributes_hash)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    check_attributes(attributes_hash)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    load_attributes(attributes_hash)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    create_attribute_writers
         
     | 
| 
      
 19 
     | 
    
         
            +
                    create_attribute_readers
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def validate_record_for_update(attributes_hash)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    raise ArgumentError, 'update action requires minimum one attribute' if attributes_hash.empty?
         
     | 
| 
      
 24 
     | 
    
         
            +
                    raise WeaviateRecord::Errors::MissingIdError, 'the record doesn\'t have an id' unless @meta_attributes['id']
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    if @custom_selected
         
     | 
| 
      
 27 
     | 
    
         
            +
                      raise WeaviateRecord::Errors::CustomQueriedRecordError,
         
     | 
| 
      
 28 
     | 
    
         
            +
                            'cannot perform update action on custom selected record'
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    check_attributes(attributes_hash)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    return unless attributes_hash['_additional'] || attributes_hash[:_additional]
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    raise WeaviateRecord::Errors::MetaAttributeError, 'cannot update meta attributes'
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def validate_and_save
         
     | 
| 
      
 38 
     | 
    
         
            +
                    if @custom_selected
         
     | 
| 
      
 39 
     | 
    
         
            +
                      raise WeaviateRecord::Errors::CustomQueriedRecordError, 'cannot modify custom selected record'
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                    return false unless valid?
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    result = create_or_update_record
         
     | 
| 
      
 44 
     | 
    
         
            +
                    raise WeaviateRecord::Errors::InternalError, 'unable to save the record on Weaviate' unless result.is_a?(Hash)
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    result
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def create_or_update_record
         
     | 
| 
      
 50 
     | 
    
         
            +
                    if @meta_attributes['id']
         
     | 
| 
      
 51 
     | 
    
         
            +
                      @connection.update_call(@meta_attributes['id'], @attributes)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    else
         
     | 
| 
      
 53 
     | 
    
         
            +
                      @connection.create_call(@attributes)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  def validate_record_for_destroy
         
     | 
| 
      
 58 
     | 
    
         
            +
                    if @custom_selected
         
     | 
| 
      
 59 
     | 
    
         
            +
                      raise WeaviateRecord::Errors::CustomQueriedRecordError,
         
     | 
| 
      
 60 
     | 
    
         
            +
                            'cannot perform destroy action on custom selected record'
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    return true if @meta_attributes['id']
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                    @attributes.each_key { |key| @attributes[key] = nil }
         
     | 
| 
      
 66 
     | 
    
         
            +
                    false
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  class_methods do
         
     | 
| 
      
 70 
     | 
    
         
            +
                    def meta_attributes(record)
         
     | 
| 
      
 71 
     | 
    
         
            +
                      meta = {}
         
     | 
| 
      
 72 
     | 
    
         
            +
                      meta['id'] = record['id']
         
     | 
| 
      
 73 
     | 
    
         
            +
                      meta['created_at'] = DateTime.strptime(record['creationTimeUnix'].to_s, '%Q')
         
     | 
| 
      
 74 
     | 
    
         
            +
                      meta['updated_at'] = DateTime.strptime(record['lastUpdateTimeUnix'].to_s, '%Q')
         
     | 
| 
      
 75 
     | 
    
         
            +
                      meta
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'weaviate'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module WeaviateRecord
         
     | 
| 
      
 6 
     | 
    
         
            +
              # This module will act as a connection to Weaviate database
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Connection
         
     | 
| 
      
 8 
     | 
    
         
            +
                # Returns a _Weaviate::Client_ object, which is used to interact with the Weaviate database.
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :client
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                # Creates a new Connection to the Weaviate database.
         
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize(collection_name = nil)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @collection_name = collection_name&.to_s
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @client = Weaviate::Client.new(
         
     | 
| 
      
 15 
     | 
    
         
            +
                    url: ENV.fetch('WEAVIATE_DATABASE_URL'),
         
     | 
| 
      
 16 
     | 
    
         
            +
                    api_key: ENV.fetch('WEAVIATE_API_KEY', nil),
         
     | 
| 
      
 17 
     | 
    
         
            +
                    model_service: ENV['WEAVIATE_VECTORIZER_MODULE']&.to_sym,
         
     | 
| 
      
 18 
     | 
    
         
            +
                    model_service_api_key: ENV.fetch('WEAVIATE_VECTORIZER_API_KEY', nil)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  )
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                # Returns the present schema of the Weaviate database.
         
     | 
| 
      
 23 
     | 
    
         
            +
                def schema_list
         
     | 
| 
      
 24 
     | 
    
         
            +
                  client.schema.list.deep_symbolize_keys!
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                # :enddoc:
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def find_call(id)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  client.objects.get(class_name: @collection_name, id: id)
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def create_call(properties)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  client.objects.create(class_name: @collection_name, properties: properties)
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def update_call(id, properties)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  client.objects.update(class_name: @collection_name, id: id, properties: properties)
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                def delete_call(id)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  client.objects.delete(class_name: @collection_name, id: id)
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def check_existence(id)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  client.objects.exists?(class_name: @collection_name, id: id)
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def delete_where(condition)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  client.objects.batch_delete(class_name: @collection_name, where: condition)
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module WeaviateRecord
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Constants # :nodoc:
         
     | 
| 
      
 5 
     | 
    
         
            +
                SPECIAL_ATTRIBUTE_MAPPINGS = { 'feature_projection' => 'featureProjection',
         
     | 
| 
      
 6 
     | 
    
         
            +
                                               'created_at' => 'creationTimeUnix',
         
     | 
| 
      
 7 
     | 
    
         
            +
                                               'updated_at' => 'lastUpdateTimeUnix',
         
     | 
| 
      
 8 
     | 
    
         
            +
                                               'explain_score' => 'explainScore' }.freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                OPERATOR_MAPPING_HASH = { '=' => 'Equal', '==' => 'Equal', '!=' => 'NotEqual',
         
     | 
| 
      
 11 
     | 
    
         
            +
                                          '>' => 'GreaterThan', '<' => 'LessThan', '>=' => 'GreaterThanEqual',
         
     | 
| 
      
 12 
     | 
    
         
            +
                                          '<=' => 'LessThanEqual', 'LIKE' => 'Like', 'CONTAINS_ANY' => 'ContainsAny',
         
     | 
| 
      
 13 
     | 
    
         
            +
                                          'CONTAINS_ALL' => 'ContainsAll' }.freeze
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                TYPE_MAPPING_HASH = { Integer => 'valueInt', String => 'valueText', Array => 'valueText',
         
     | 
| 
      
 16 
     | 
    
         
            +
                                      Float => 'valueNumber', TrueClass => 'valueBoolean', FalseClass => 'valueBoolean' }.freeze
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                META_ATTRIBUTES = %w[vector certainty distance feature_projection classification
         
     | 
| 
      
 19 
     | 
    
         
            +
                                     creation_at updated_at score explain_score summary].freeze
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                UUID_REGEX = /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i.freeze
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            WeaviateRecord::Constants.freeze
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module WeaviateRecord # :nodoc: all
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Errors
         
     | 
| 
      
 5 
     | 
    
         
            +
                # Used when an un-queried attribute is accessed
         
     | 
| 
      
 6 
     | 
    
         
            +
                class MissingAttributeError < StandardError
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # Used when an undefined attribute is accessed
         
     | 
| 
      
 10 
     | 
    
         
            +
                class InvalidAttributeError < StandardError
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # Used when a collection is not found in the schema
         
     | 
| 
      
 14 
     | 
    
         
            +
                class CollectionNotFound < StandardError
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                # Used when a record without id is updated
         
     | 
| 
      
 18 
     | 
    
         
            +
                class MissingIdError < StandardError
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                # Used when a custom queried record is updated
         
     | 
| 
      
 22 
     | 
    
         
            +
                class CustomQueriedRecordError < StandardError
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                # Used when a meta attribute is updated
         
     | 
| 
      
 26 
     | 
    
         
            +
                class MetaAttributeError < StandardError
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                # Used when there is a problem with Weaviate
         
     | 
| 
      
 30 
     | 
    
         
            +
                class InternalError < StandardError
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                # Used when the Sorting order is invalid
         
     | 
| 
      
 34 
     | 
    
         
            +
                class SortingOptionError < StandardError
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # Used when the where query is invalid
         
     | 
| 
      
 38 
     | 
    
         
            +
                class InvalidWhereQueryError < StandardError
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                # Used when the operator in where query is invalid
         
     | 
| 
      
 42 
     | 
    
         
            +
                class InvalidOperatorError < StandardError
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                # Used when the value type in where query is invalid
         
     | 
| 
      
 46 
     | 
    
         
            +
                class InvalidValueTypeError < StandardError
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                # Used when the record not found
         
     | 
| 
      
 50 
     | 
    
         
            +
                class RecordNotFoundError < StandardError
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                # Used for the errors thrown by weaviate server
         
     | 
| 
      
 54 
     | 
    
         
            +
                class ServerError < StandardError
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                # Used when destroy_all called without where conditions
         
     | 
| 
      
 58 
     | 
    
         
            +
                class MissingWhereCondition < StandardError
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                # Raised when where condition is not getting converted to Ruby hash
         
     | 
| 
      
 62 
     | 
    
         
            +
                class WhereQueryConversionError < StandardError
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                # Raised when required argument is empty
         
     | 
| 
      
 66 
     | 
    
         
            +
                class EmptyPrompt < StandardError
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module WeaviateRecord
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Inspect # :nodoc:
         
     | 
| 
      
 5 
     | 
    
         
            +
                def inspect
         
     | 
| 
      
 6 
     | 
    
         
            +
                  special_attributes, inspection = format_attributes
         
     | 
| 
      
 7 
     | 
    
         
            +
                  string = to_s
         
     | 
| 
      
 8 
     | 
    
         
            +
                  string[-1] = ' '
         
     | 
| 
      
 9 
     | 
    
         
            +
                  string << "id: #{special_attributes['id'].inspect} " << inspection
         
     | 
| 
      
 10 
     | 
    
         
            +
                  string << " created_at: #{special_attributes['created_at'].inspect}" if special_attributes.key? 'created_at'
         
     | 
| 
      
 11 
     | 
    
         
            +
                  string << " updated_at: #{special_attributes['updated_at'].inspect}" if special_attributes.key? 'updated_at'
         
     | 
| 
      
 12 
     | 
    
         
            +
                  string << '>'
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                private
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def format_attributes
         
     | 
| 
      
 18 
     | 
    
         
            +
                  attributes_list = { **@meta_attributes, **@attributes }
         
     | 
| 
      
 19 
     | 
    
         
            +
                  special_attributes = attributes_list.slice('id', 'created_at', 'updated_at')
         
     | 
| 
      
 20 
     | 
    
         
            +
                  attributes_list.except!(*special_attributes.keys)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  inspection = attributes_list.sort.map do |key, value|
         
     | 
| 
      
 22 
     | 
    
         
            +
                    format_for_inspect(key, value)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end.join(', ')
         
     | 
| 
      
 24 
     | 
    
         
            +
                  [special_attributes, inspection]
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def format_for_inspect(key, value)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  formatted_value = case value
         
     | 
| 
      
 29 
     | 
    
         
            +
                                    when String then value.truncate(25).inspect
         
     | 
| 
      
 30 
     | 
    
         
            +
                                    when Array then key == 'vector' ? "[#{value.first(4).join(', ')}...]" : value.inspect
         
     | 
| 
      
 31 
     | 
    
         
            +
                                    else value.inspect
         
     | 
| 
      
 32 
     | 
    
         
            +
                                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  "#{key.underscore}: #{formatted_value}"
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module WeaviateRecord
         
     | 
| 
      
 4 
     | 
    
         
            +
              module MethodMissing # :nodoc:
         
     | 
| 
      
 5 
     | 
    
         
            +
                private
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def list_of_all_attributes
         
     | 
| 
      
 8 
     | 
    
         
            +
                  [*WeaviateRecord::Schema.find_collection(collection_name).attributes_list,
         
     | 
| 
      
 9 
     | 
    
         
            +
                   *WeaviateRecord::Constants::META_ATTRIBUTES]
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def method_missing(method, *args, &block)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  if list_of_all_attributes.include? method.to_s
         
     | 
| 
      
 14 
     | 
    
         
            +
                    raise WeaviateRecord::Errors::MissingAttributeError, "missing attribute: #{method}"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  super
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def respond_to_missing?(method, include_all = false)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  list_of_all_attributes.include?(method.to_s) ? true : super
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module WeaviateRecord
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Queries # :nodoc:
         
     | 
| 
      
 5 
     | 
    
         
            +
                # This module provides method for ask query
         
     | 
| 
      
 6 
     | 
    
         
            +
                module Ask
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # Answers the question using the QnA module with the help of the records in the database.
         
     | 
| 
      
 8 
     | 
    
         
            +
                  #
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # Requires QNA_INFERENCE_API to be set in the weaviate instance.
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # The answer will be available in the _result_ key of the _answer_ meta attribute.
         
     | 
| 
      
 11 
     | 
    
         
            +
                  #
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # You can also optionally pass an array of attributes to searched for the answer.
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # ==== Example:
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #   Article.create(content: 'the name is Sparrow')
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #   Article.select(_additional: { answer: :result }).ask('whats your name?')
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #   # => [#<Article:0x0000000109a85de0 id: nil answer: {"result"=>"Sparrow"}>]
         
     | 
| 
      
 18 
     | 
    
         
            +
                  def ask(question, on_attributes: [])
         
     | 
| 
      
 19 
     | 
    
         
            +
                    question.to_str
         
     | 
| 
      
 20 
     | 
    
         
            +
                    raise WeaviateRecord::Errors::EmptyPrompt, 'text cannot be empty' if question.empty?
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    attributes = on_attributes.map(&:to_s)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @ask = "{ question: #{question.gsub('"', "'").inspect}" \
         
     | 
| 
      
 24 
     | 
    
         
            +
                           "#{", properties: #{attributes}" if attributes.present?} }"
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @loaded = false
         
     | 
| 
      
 26 
     | 
    
         
            +
                    self
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module WeaviateRecord
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Queries
         
     | 
| 
      
 5 
     | 
    
         
            +
                # Bm25 is an algorithm to perform keyword based search on collection provided by Weaviate
         
     | 
| 
      
 6 
     | 
    
         
            +
                # This class contains functions to perform that query
         
     | 
| 
      
 7 
     | 
    
         
            +
                module Bm25
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # Perform a keyword based search on the collection.
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # You can also optionally pass an array of attributes to search in the collection.
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # ==== Example:
         
     | 
| 
      
 12 
     | 
    
         
            +
                  #   Article.create(content: 'This is a movie about friendship, action and adventure')
         
     | 
| 
      
 13 
     | 
    
         
            +
                  #   # => #<Article:0x00000001052091e8 id: "983c0970-2c65-4c38-a93f-2ca9272d784b"... >
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #   Article.bm25('friendship movie')
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #   # => [#<Article:0x00000001052091e8 id: "983c0970-2c65-4c38-a93f-2ca9272d784b"... >]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def bm25(text, on_attributes: [])
         
     | 
| 
      
 18 
     | 
    
         
            +
                    text = text.to_str
         
     | 
| 
      
 19 
     | 
    
         
            +
                    return self if text.empty?
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    attributes = on_attributes.map(&:to_s)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @keyword_search = "{ query: #{text.gsub('"', "'").inspect}" \
         
     | 
| 
      
 23 
     | 
    
         
            +
                                      "#{", properties: #{attributes}" if attributes.present?} }"
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @loaded = false
         
     | 
| 
      
 25 
     | 
    
         
            +
                    self
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     |