Skip to content

Instantly share code, notes, and snippets.

@jarthod
Forked from romanbsd/compressed.rb
Last active August 16, 2022 13:39
Show Gist options
  • Save jarthod/6c7ddbea1c47b9ca5f159b6c28f81374 to your computer and use it in GitHub Desktop.
Save jarthod/6c7ddbea1c47b9ca5f159b6c28f81374 to your computer and use it in GitHub Desktop.
Compressed fields in Mongoid 6.4+
require 'zstd-ruby'
class CompressedHash < Hash
DICTIONARY = IO.read('config/dictionaries/1')
def mongoize
if size > 0 # only compress non-empty hash
# BSON::Binary.new(Zstd.compress(self.to_bson.to_s))
BSON::Binary.new(Zstd.compress_using_dict(self.to_bson.to_s, DICTIONARY))
else
self
end
end
class << self
# Get the object as it was stored in the database, and instantiate
# this custom class from it.
def demongoize(object)
case object
# when BSON::Binary then CompressedHash[BSON::Document.from_bson(BSON::ByteBuffer.new(Zstd.decompress(object.data)))]
when BSON::Binary then CompressedHash[BSON::Document.from_bson(BSON::ByteBuffer.new(Zstd.decompress_using_dict(object.data, DICTIONARY)))]
when Hash then CompressedHash[object]
else object
end
end
# Takes any possible object and converts it to how it would be
# stored in the database.
def mongoize(object)
case object
when CompressedHash then object.mongoize
when Hash then CompressedHash[object].mongoize
else object
end
end
# Converts the object that was supplied to a criteria and converts it
# into a database friendly form.
alias_method :evolve, :mongoize
end
end
require 'zlib'
class CompressedString < String
def mongoize
if bytesize > 1000 # only compress over 1k
BSON::Binary.new(Zlib::Deflate.deflate(self))
else
self
end
end
class << self
# Get the object as it was stored in the database, and instantiate
# this custom class from it.
def demongoize(object)
case object
when BSON::Binary then self.new(Zlib::Inflate.inflate(object.data))
when String then self.new(object)
else object
end
end
# Takes any possible object and converts it to how it would be
# stored in the database.
def mongoize(object)
case object
when self then object.mongoize
when String then self.new(object).mongoize
else object
end
end
# Converts the object that was supplied to a criteria and converts it
# into a database friendly form.
alias_method :evolve, :mongoize
end
end
# Decompress-only class to support removing compression smoothly
class UnCompressedString < CompressedString
def mongoize
self
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment