Class: RubynCode::Memory::Search

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyn_code/memory/search.rb

Overview

Searches memories using SQLite FTS5 full-text search and standard queries. Every search method automatically increments access_count and updates last_accessed_at on returned records, reinforcing frequently-accessed memories against decay.

Instance Method Summary collapse

Constructor Details

#initialize(db, project_path:) ⇒ Search

Returns a new instance of Search.

Parameters:

  • db (DB::Connection)

    database connection

  • project_path (String)

    scoping path for searches



15
16
17
18
# File 'lib/rubyn_code/memory/search.rb', line 15

def initialize(db, project_path:)
  @db = db
  @project_path = project_path
end

Instance Method Details

#by_category(category, limit: 10) ⇒ Array<MemoryRecord>

Returns memories filtered by category.

Parameters:

  • category (String)
  • limit (Integer) (defaults to: 10)

    maximum results (default 10)

Returns:



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/rubyn_code/memory/search.rb', line 85

def by_category(category, limit: 10)
  rows = @db.query(<<~SQL, [@project_path, category, limit]).to_a
    SELECT id, project_path, tier, category, content,
           relevance_score, access_count, last_accessed_at,
           expires_at, metadata, created_at
    FROM memories
    WHERE project_path = ?
      AND category = ?
    ORDER BY relevance_score DESC, created_at DESC
    LIMIT ?
  SQL

  records = rows.map { |row| build_record(row) }
  touch_accessed(records)
  records
end

#by_tier(tier, limit: 10) ⇒ Array<MemoryRecord>

Returns memories filtered by tier.

Parameters:

  • tier (String)
  • limit (Integer) (defaults to: 10)

    maximum results (default 10)

Returns:



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/rubyn_code/memory/search.rb', line 107

def by_tier(tier, limit: 10)
  rows = @db.query(<<~SQL, [@project_path, tier, limit]).to_a
    SELECT id, project_path, tier, category, content,
           relevance_score, access_count, last_accessed_at,
           expires_at, metadata, created_at
    FROM memories
    WHERE project_path = ?
      AND tier = ?
    ORDER BY relevance_score DESC, created_at DESC
    LIMIT ?
  SQL

  records = rows.map { |row| build_record(row) }
  touch_accessed(records)
  records
end

#recent(limit: 10) ⇒ Array<MemoryRecord>

Returns the most recently created memories.

Parameters:

  • limit (Integer) (defaults to: 10)

    maximum results (default 10)

Returns:



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rubyn_code/memory/search.rb', line 64

def recent(limit: 10)
  rows = @db.query(<<~SQL, [@project_path, limit]).to_a
    SELECT id, project_path, tier, category, content,
           relevance_score, access_count, last_accessed_at,
           expires_at, metadata, created_at
    FROM memories
    WHERE project_path = ?
    ORDER BY created_at DESC
    LIMIT ?
  SQL

  records = rows.map { |row| build_record(row) }
  touch_accessed(records)
  records
end

#search(query, tier: nil, category: nil, limit: 10) ⇒ Array<MemoryRecord>

Full-text search across memory content using FTS5.

Parameters:

  • query (String)

    the search query (FTS5 syntax supported)

  • tier (String, nil) (defaults to: nil)

    filter by tier

  • category (String, nil) (defaults to: nil)

    filter by category

  • limit (Integer) (defaults to: 10)

    maximum results (default 10)

Returns:



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rubyn_code/memory/search.rb', line 27

def search(query, tier: nil, category: nil, limit: 10)
  conditions = ['m.project_path = ?']
  params = [@project_path]

  if tier
    conditions << 'm.tier = ?'
    params << tier
  end

  if category
    conditions << 'm.category = ?'
    params << category
  end

  params << query
  params << limit

  rows = @db.query(<<~SQL, params).to_a
    SELECT m.id, m.project_path, m.tier, m.category, m.content,
           m.relevance_score, m.access_count, m.last_accessed_at,
           m.expires_at, m.metadata, m.created_at
    FROM memories m
    WHERE #{conditions.join(' AND ')}
      AND m.content LIKE '%' || ? || '%'
    ORDER BY m.relevance_score DESC, m.created_at DESC
    LIMIT ?
  SQL

  records = rows.map { |row| build_record(row) }
  touch_accessed(records)
  records
end