class SlugDB
Zero dependecy NoSQL, file based database
Constants
- VERSION
Public Class Methods
new(file, thread_safe: false, ultra_safe: false)
click to toggle source
# File lib/slugdb.rb, line 9 def initialize(file, thread_safe: false, ultra_safe: false) @pstore = PStore.new(file, thread_safe).tap { |s| s.ultra_safe = ultra_safe } @pstore.transaction do |db| db[:main] ||= {} db[:indexes] ||= {} end end
Public Instance Methods
add_index(name:, pk:, sk:)
click to toggle source
# File lib/slugdb.rb, line 32 def add_index(name:, pk:, sk:) # rubocop:disable Naming/MethodParameterName @pstore.transaction do |db| db[:indexes] ||= {} db[:indexes][name] = { pk: pk, sk: sk } end reindex! { name => { pk: pk, sk: sk } } end
delete_item(pk:, sk:, **_)
click to toggle source
rubocop:disable Naming/MethodParameterName
# File lib/slugdb.rb, line 75 def delete_item(pk:, sk:, **_) item = get_item(pk: pk, sk: sk) return if item.nil? indexes = list_indexes @pstore.transaction { |db| perform_delete(db, indexes, pk, sk, item) } item end
get_item(pk:, sk:, **_)
click to toggle source
# File lib/slugdb.rb, line 50 def get_item(pk:, sk:, **_) # rubocop:disable Naming/MethodParameterName @pstore.transaction do |db| next if db[:main][pk].nil? || db[:main][pk][sk].nil? db[:main][pk][sk] end end
list_indexes()
click to toggle source
# File lib/slugdb.rb, line 42 def list_indexes @pstore.transaction { |db| db[:indexes] } end
list_partitions()
click to toggle source
# File lib/slugdb.rb, line 46 def list_partitions @pstore.transaction { |db| db[:main].keys } end
put_item(pk:, sk:, **attributes)
click to toggle source
# File lib/slugdb.rb, line 58 def put_item(pk:, sk:, **attributes) # rubocop:disable Naming/MethodParameterName old_item = get_item(pk: pk, sk: sk) new_item = attributes.merge(pk: pk, sk: sk) indexes = list_indexes @pstore.transaction do |db| perform_delete(db, indexes, pk, sk, old_item) db[:main][pk] ||= {} db[:main][pk][sk] = new_item indexes.each { |name, schema| index_item(db, new_item, name, schema) } end new_item end
query(pk:, index: :main, select: ->(sk) { true }
click to toggle source
rubocop:disable Lint/UnusedBlockArgument,Naming/MethodParameterName rubocop:disable Metrics/PerceivedComplexity,Metrics/MethodLength rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,
# File lib/slugdb.rb, line 89 def query(pk:, index: :main, select: ->(sk) { true }, filter: ->(item) { true }) if index == :main @pstore.transaction do |db| db[index] .fetch(pk, {}) .map { |_, records| records } .select { |item| select[item[:sk]] } .filter { |item| filter[item] } end else name, schema = list_indexes.find { |name,| name == index } @pstore.transaction do |db| db[name] .fetch(pk, {}) .map do |_, isk_records| isk_records.map do |_, pk_records| pk_records.map { |_, sk_records| sk_records } end end # rubocop:disable Style/MultilineBlockChain .flatten(2) .select { |item| select[item[schema[:sk]]] } .filter { |item| filter[item] } end end end
reindex!()
click to toggle source
# File lib/slugdb.rb, line 17 def reindex! indexes = list_indexes @pstore.transaction { |db| db[:main] }.each do |pk, records| records.each do |sk, record| @pstore.transaction do |db| indexes.each do |name, schema| index_item(db, record.merge(pk: pk, sk: sk), name, schema) end end end end nil end
Private Instance Methods
delete_if_empty?(hash, key)
click to toggle source
# File lib/slugdb.rb, line 146 def delete_if_empty?(hash, key) hash.delete(key) if hash[key].empty? end
index_item(db, item, name, schema)
click to toggle source
rubocop:enable Lint/UnusedBlockArgument,Naming/MethodParameterName rubocop:enable Metrics/PerceivedComplexity,Metrics/MethodLength rubocop:enable Metrics/CyclomaticComplexity,Metrics/AbcSize
# File lib/slugdb.rb, line 120 def index_item(db, item, name, schema) # rubocop:disable Metrics/AbcSize return unless item.key?(schema[:pk]) && item.key?(schema[:sk]) db[name] ||= {} db[name][item[schema[:pk]]] ||= {} db[name][item[schema[:pk]]][item[schema[:sk]]] ||= {} db[name][item[schema[:pk]]][item[schema[:sk]]][item[:pk]] ||= {} db[name][item[schema[:pk]]][item[schema[:sk]]][item[:pk]][item[:sk]] = item end
perform_delete(db, indexes, pk, sk, item)
click to toggle source
# File lib/slugdb.rb, line 130 def perform_delete(db, indexes, pk, sk, item) # rubocop:disable Naming/MethodParameterName,Metrics/AbcSize return if item.nil? db[:main][pk].delete(sk) db[:main].delete(pk) if db[:main][pk].empty? indexes.each do |name, schema| next unless item.key?(schema[:pk]) && item.key?(schema[:sk]) db[name][item[schema[:pk]]][item[schema[:sk]]][item[:pk]].delete(item[:sk]) delete_if_empty?(db[name][item[schema[:pk]]][item[schema[:sk]]], item[:pk]) delete_if_empty?(db[name][item[schema[:pk]]], item[schema[:sk]]) delete_if_empty?(db[name], item[schema[:pk]]) end end