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



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

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



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

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
36
# File 'lib/factbase/indexed/indexed_factbase.rb', line 33

def insert
  @idx.clear
  Factbase::IndexedFact.new(@origin.insert, @idx)
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



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

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

#sizeInteger

Size, the total number of facts in the factbase.

Returns:

  • (Integer)

    How many facts are in there



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

def size
  @origin.size
end

#to_term(query) ⇒ Factbase::Term

Convert a query to a term.

Parameters:

  • query (String)

    The query to convert

Returns:



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

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)



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

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