Class: Lunar::Index

Inherits:
Object
  • Object
show all
Defined in:
lib/lunar/index.rb

Overview

Handles the management of indices for a given namespace. Although you may use this directly, it’s much more convenient to use ‘Lunar::index` and `Lunar::delete`.

See Also:

  • index
  • delete

Constant Summary collapse

FUZZY_MAX_LENGTH =
100
MissingID =
Class.new(StandardError)
FuzzyFieldTooLong =
Class.new(StandardError)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(namespace) ⇒ Lunar::Index

This is actually wrapped by ‘Lunar.index` and is not inteded to be used directly.

Parameters:

  • the (#to_s)

    namespace of the document you want to index.

See Also:

  • index


25
26
27
28
29
30
31
# File 'lib/lunar/index.rb', line 25

def initialize(namespace)
  @nest       = Lunar.nest[namespace]
  @metaphones = @nest[:Metaphones]
  @numbers    = @nest[:Numbers]
  @sortables  = @nest[:Sortables]
  @fuzzies    = @nest[:Fuzzies]
end

Instance Attribute Details

#fuzziesObject (readonly)

Returns the value of attribute fuzzies.



18
19
20
# File 'lib/lunar/index.rb', line 18

def fuzzies
  @fuzzies
end

#metaphonesObject (readonly)

Returns the value of attribute metaphones.



15
16
17
# File 'lib/lunar/index.rb', line 15

def metaphones
  @metaphones
end

#nestObject (readonly)

Returns the value of attribute nest.



14
15
16
# File 'lib/lunar/index.rb', line 14

def nest
  @nest
end

#numbersObject (readonly)

Returns the value of attribute numbers.



16
17
18
# File 'lib/lunar/index.rb', line 16

def numbers
  @numbers
end

#sortablesObject (readonly)

Returns the value of attribute sortables.



17
18
19
# File 'lib/lunar/index.rb', line 17

def sortables
  @sortables
end

Instance Method Details

#delete(existing_id) ⇒ nil

Deletes everything related to an existing document given its ‘id`.

Parameters:

  • id (#to_s)

    the document’s id.

Returns:

  • (nil)


165
166
167
168
169
170
171
# File 'lib/lunar/index.rb', line 165

def delete(existing_id)
  id(existing_id)
  delete_metaphones
  delete_numbers
  delete_sortables
  delete_fuzzies
end

#fuzzy(att, value) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/lunar/index.rb', line 173

def fuzzy(att, value)
  if value.to_s.length > FUZZY_MAX_LENGTH
    raise FuzzyFieldTooLong,
      "#{att} has a value #{value} exceeding the max #{FUZZY_MAX_LENGTH}"
  end

  words = Words.new(value).uniq

  fuzzy_words_and_parts(words) do |word, parts|
    parts.each do |part, encoded|
      fuzzies[att][encoded].zadd(1, id)
    end
    fuzzies[id][att].sadd word
  end

  delete_fuzzies_for(att, fuzzies[id][att].smembers - words, words)
end

#id(value = nil) ⇒ String

Get / Set the id of the document The ‘id` is used for all other keys to define the structure of the keys, therefore it’s imperative that you set it first.

Examples:


# Wrong usage:
Lunar.index :Gadget do |i|
  i.text :name, 'iPad'
end
# => raise MissingID

# Correct usage:
Lunar.index :Gadget do |i|
  i.id 1001 # this appears before anything.
  i.text :name, 'iPad' # ok now you can set other fields.
end

Parameters:

  • the (#to_s)

    id of the document you want to index.

Returns:

  • (String)

    the ‘id` you set.

Raises:



54
55
56
57
# File 'lib/lunar/index.rb', line 54

def id(value = nil)
  @id = value.to_s if value
  @id or raise MissingID, "In order to index a document, you need an `id`"
end

#number(att, value) ⇒ Boolean

Adds a numeric index for ‘att` with `value`.

Examples:


Lunar.index :Gadget do |i|
  i.id 1001
  i.number :price, 200
end

# Executes the ff: in redis:
#
# ZADD Lunar:Gadget:price 200

Parameters:

  • att (Symbol)

    the field name in your document.

  • value (Numeric)

    the numeric value of ‘att`.

Returns:

  • (Boolean)

    whether or not the value was added



120
121
122
# File 'lib/lunar/index.rb', line 120

def number(att, value)
  numbers[att].zadd(value, id)
end

#sortable(att, value) ⇒ String

Adds a sortable index for ‘att` with `value`.

Examples:


class Gadget
  def self.[](id)
    # find the gadget using id here
  end
end

Lunar.index Gadget do |i|
  i.id 1001
  i.text 'apple macbook pro'
  i.sortable :votes, 50
end

Lunar.index Gadget do |i|
  i.id 1002
  i.text 'apple iphone 3g'
  i.sortable :votes, 20
end

results = Lunar.search(Gadget, :q => 'apple')
results.sort(:by => :votes, :order => 'DESC')
# returns [Gadget[1001], Gadget[1002]]

results.sort(:by => :votes, :order => 'ASC')
# returns [Gadget[1002], Gadget[1001]]

Parameters:

  • att (Symbol)

    the field you want to have sortability.

  • value (String, Numeric)

    the value of the sortable field.

Returns:

  • (String)

    the response from the redis server.



157
158
159
# File 'lib/lunar/index.rb', line 157

def sortable(att, value)
  sortables[id][att].set(value)
end

#text(att, value) ⇒ Array<String>

Indexes all the metaphone equivalents of the words in value except for words included in Stopwords.

Examples:


Lunar.index :Gadget do |i|
  i.id 1001
  i.text :title, "apple macbook pro"
end

# Executes the ff: in redis:
#
# ZADD Lunar:Gadget:title:APL  1 1001
# ZADD Lunar:Gadget:title:MKBK 1 1001
# ZADD Lunar:Gadget:title:PR   1 1001
#
# In addition a reference of all the words are stored
# SMEMBERS Lunar:Gadget:Metaphones:1001:title
# => (APL, MKBK, PR)

Parameters:

  • att (Symbol)

    the field name in your document

  • value (String)

    the content of the field name

Returns:

  • (Array<String>)

    all the metaphones added for the document.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/lunar/index.rb', line 83

def text(att, value)
  old = metaphones[id][att].smembers
  new = []

  Scoring.new(value).scores.each do |word, score|
    metaphone = Lunar.metaphone(word)

    nest[att][metaphone].zadd(score, id)
    metaphones[id][att].sadd(metaphone)
    new << metaphone
  end

  (old - new).each do |metaphone|
    nest[att][metaphone].zrem(id)
    metaphones[id][att].srem(metaphone)
  end

  return new
end