Class: Factbase::IndexedFactbase

Inherits:
Object
  • Object
show all
Defined in:
lib/factbase/indexed/indexed_factbase.rb

Overview

A factbase with an index.

Author

Yegor Bugayenko ([email protected])

Copyright

Copyright © 2024-2025 Yegor Bugayenko

License

MIT

Instance Method Summary collapse

Constructor Details

#initialize(origin, idx = {}) ⇒ IndexedFactbase

Constructor.

Parameters:

  • origin (Factbase)

    Original factbase to decorate

  • idx (Hash) (defaults to: {})

    Index to use



24
25
26
27
28
29
# File 'lib/factbase/indexed/indexed_factbase.rb', line 24

def initialize(origin, idx = {})
  raise 'Wrong type of original' unless origin.respond_to?(:query)
  @origin = origin
  raise 'Wrong type of index' unless idx.is_a?(Hash)
  @idx = idx
end

Instance Method Details

#exportString

Export it into a chain of bytes, including both data and index.

Here is how you can export it to a file, for example:

fb = Factbase::IndexedFactbase.new(Factbase.new)
fb.insert.foo = 42
File.binwrite("foo.fb", fb.export)

The data is binary, it’s not a text!

Returns:

  • (String)

    Binary string containing serialized data and index



77
78
79
# File 'lib/factbase/indexed/indexed_factbase.rb', line 77

def export
  Marshal.dump({ maps: @origin.export, idx: @idx })
end

#import(bytes) ⇒ Object

Import from a chain of bytes, including both data and index.

Here is how you can read it from a file, for example:

fb = Factbase::IndexedFactbase.new(Factbase.new)
fb.import(File.binread("foo.fb"))

The facts that existed in the factbase before importing will remain there. The facts from the incoming byte stream will be added to them. If the byte stream doesn’t contain an index (for backward compatibility), the index will be empty and will be built on first use.

Parameters:

  • bytes (String)

    Binary string to import



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/factbase/indexed/indexed_factbase.rb', line 94

def import(bytes)
  raise 'Empty input, cannot load a factbase' if bytes.empty?
  data = Marshal.load(bytes)
  if data.is_a?(Hash) && data.key?(:maps)
    @origin.import(data[:maps])
    @idx.merge!(data[:idx]) if data[:idx].is_a?(Hash)
  else
    @origin.import(bytes)
    @idx.clear
  end
end

#insertFactbase::Fact

Insert a new fact and return it.

Returns:



33
34
35
# File 'lib/factbase/indexed/indexed_factbase.rb', line 33

def insert
  Factbase::IndexedFact.new(@origin.insert, @idx, fresh: true)
end

#query(term, maps = nil) ⇒ Object

Create a query capable of iterating.

Parameters:

  • term (String)

    The term to use

  • maps (Array<Hash>) (defaults to: nil)

    Possible maps to use



49
50
51
52
53
# File 'lib/factbase/indexed/indexed_factbase.rb', line 49

def query(term, maps = nil)
  term = to_term(term) if term.is_a?(String)
  q = @origin.query(term, maps)
  Factbase::IndexedQuery.new(q, @idx, self)
end

#sizeInteger

Size, the total number of facts in the factbase.

Returns:

  • (Integer)

    How many facts are in there



108
109
110
# File 'lib/factbase/indexed/indexed_factbase.rb', line 108

def size
  @origin.size
end

#to_term(query) ⇒ Factbase::Term

Convert a query to a term.

Parameters:

  • query (String)

    The query to convert

Returns:



40
41
42
43
44
# File 'lib/factbase/indexed/indexed_factbase.rb', line 40

def to_term(query)
  t = @origin.to_term(query)
  t.redress!(Factbase::IndexedTerm, idx: @idx)
  t
end

#txnFactbase::Churn

Run an ACID transaction.

Returns:

  • (Factbase::Churn)

    How many facts have been changed (zero if rolled back)



57
58
59
60
61
62
63
64
# File 'lib/factbase/indexed/indexed_factbase.rb', line 57

def txn
  result =
    @origin.txn do |fbt|
      yield Factbase::IndexedFactbase.new(fbt, @idx)
    end
  @idx.clear
  result
end