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 =

This constant is in place to maintain a certain level of performance. Fuzzy searching internally stores an index per letter i.e. for Quentin q qu que quen quent quenti quentin

This can become pretty unweildy very fast, so we limit the length of all fuzzy fields.

100
TEXT =

The following are all used to construct redis keys

:Text
METAPHONES =
:Metaphones
NUMBERS =
:Numbers
SORTABLES =
:Sortables
FUZZIES =
:Fuzzies
FIELDS =
:Fields
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


46
47
48
49
50
51
52
53
# File 'lib/lunar/index.rb', line 46

def initialize(namespace)
  @nest       = Lunar.nest[namespace]
  @metaphones = @nest[METAPHONES]
  @numbers    = @nest[NUMBERS]
  @sortables  = @nest[SORTABLES]
  @fuzzies    = @nest[FUZZIES]
  @fields     = @nest[FIELDS]
end

Instance Attribute Details

#fieldsObject (readonly)

Returns the value of attribute fields.



39
40
41
# File 'lib/lunar/index.rb', line 39

def fields
  @fields
end

#fuzziesObject (readonly)

Returns the value of attribute fuzzies.



38
39
40
# File 'lib/lunar/index.rb', line 38

def fuzzies
  @fuzzies
end

#metaphonesObject (readonly)

Returns the value of attribute metaphones.



35
36
37
# File 'lib/lunar/index.rb', line 35

def metaphones
  @metaphones
end

#nestObject (readonly)

Returns the value of attribute nest.



34
35
36
# File 'lib/lunar/index.rb', line 34

def nest
  @nest
end

#numbersObject (readonly)

Returns the value of attribute numbers.



36
37
38
# File 'lib/lunar/index.rb', line 36

def numbers
  @numbers
end

#sortablesObject (readonly)

Returns the value of attribute sortables.



37
38
39
# File 'lib/lunar/index.rb', line 37

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)


194
195
196
197
198
199
200
201
202
# File 'lib/lunar/index.rb', line 194

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

  delete_field_meta
end

#fuzzy(att, value) ⇒ Object



204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/lunar/index.rb', line 204

def fuzzy(att, value)
  assert_valid_fuzzy(value, att)

  clear_fuzzy_field(att)

  words = Words.new(value, [:downcase, :uniq])

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

  fields[FUZZIES].sadd att
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:



76
77
78
79
# File 'lib/lunar/index.rb', line 76

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, purge = true) ⇒ 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



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/lunar/index.rb', line 135

def number(att, value, purge = true)
  if value.kind_of?(Enumerable)
    clear_number_field(att)

    value.each { |v| number(att, v, false) } and return
  end
  
  clear_number_field(att)  if purge

  numbers[att].zadd(value, id)
  numbers[att][value].zadd(1, id)
  numbers[id][att].sadd(value)

  fields[NUMBERS].sadd att
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.



184
185
186
187
188
# File 'lib/lunar/index.rb', line 184

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

  fields[SORTABLES].sadd att
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.



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/lunar/index.rb', line 105

def text(att, value)
  clear_text_field(att)

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

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

  fields[TEXT].sadd(att)
end