or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-querying.mdindex-building.mdindex.mdsearching.mdtext-processing.mdutilities.md

searching.mddocs/

0

# Searching

1

2

Search execution engine providing query processing, scoring, and result ranking. The search system supports both simple string queries and advanced programmatic query building with comprehensive query syntax including field restrictions, wildcards, fuzzy matching, and boolean operators.

3

4

## Capabilities

5

6

### Index Class

7

8

The built search index that provides query execution capabilities.

9

10

```javascript { .api }

11

/**

12

* Search index created by the Builder

13

*/

14

class Index {

15

/**

16

* Create a new Index instance (usually via Builder.build())

17

* @param {Object} attrs - Index attributes and configuration

18

*/

19

constructor(attrs);

20

21

/**

22

* Search the index using query string syntax

23

* @param {string} queryString - Query string with optional field restrictions, wildcards, etc.

24

* @returns {Array<Object>} - Array of search results with ref and score properties

25

*/

26

search(queryString);

27

28

/**

29

* Build queries programmatically for complex search logic

30

* @param {Function} builderFunction - Function that receives a Query builder instance

31

* @returns {Array<Object>} - Array of search results with ref and score properties

32

*/

33

query(builderFunction);

34

35

/**

36

* Serialize the index to JSON for storage or transmission

37

* @returns {Object} - Serialized index data

38

*/

39

toJSON();

40

41

/**

42

* Load an index from serialized JSON data

43

* @param {Object} serializedIndex - Previously serialized index

44

* @returns {lunr.Index} - Reconstructed index instance

45

*/

46

static load(serializedIndex);

47

}

48

49

/**

50

* Search result object

51

* @typedef {Object} SearchResult

52

* @property {string} ref - Document reference (as set by Builder.ref())

53

* @property {number} score - Relevance score (higher = more relevant)

54

* @property {Object} matchData - Optional match metadata and term positions

55

*/

56

```

57

58

**Usage Examples:**

59

60

```javascript

61

const lunr = require('lunr');

62

63

// Create index

64

const idx = lunr(function () {

65

this.ref('id');

66

this.field('title');

67

this.field('content');

68

69

this.add({ id: '1', title: 'JavaScript Guide', content: 'Learn JavaScript programming' });

70

this.add({ id: '2', title: 'Node.js Tutorial', content: 'Server-side JavaScript with Node.js' });

71

});

72

73

// Simple text search

74

const results = idx.search('javascript');

75

// Returns: [

76

// { ref: '1', score: 0.693 },

77

// { ref: '2', score: 0.405 }

78

// ]

79

80

// Field-specific search

81

const titleResults = idx.search('title:guide');

82

// Returns: [{ ref: '1', score: 1.099 }]

83

84

// Multiple terms

85

const multiResults = idx.search('javascript tutorial');

86

// Returns results containing either term, scored by relevance

87

```

88

89

### Query String Syntax

90

91

Comprehensive query string syntax for various search operations.

92

93

```javascript { .api }

94

/**

95

* Query string syntax patterns:

96

*

97

* Simple terms: "javascript node"

98

* Field restrictions: "title:guide", "content:tutorial"

99

* Required terms: "+javascript +tutorial" (both must be present)

100

* Prohibited terms: "-deprecated" (must not be present)

101

* Wildcards: "java*" (prefix), "*script" (suffix)

102

* Fuzzy search: "tutorial~1" (edit distance of 1)

103

* Term boosting: "important^10" (boost by factor of 10)

104

* Grouping: "+(javascript node.js) -deprecated"

105

*/

106

```

107

108

**Usage Examples:**

109

110

```javascript

111

// Field-specific searches

112

idx.search('title:javascript'); // Only search in title field

113

idx.search('title:guide content:node'); // Search title for "guide", content for "node"

114

115

// Boolean operators

116

idx.search('+javascript +tutorial'); // Must contain both terms

117

idx.search('+javascript -deprecated'); // Must contain "javascript", must not contain "deprecated"

118

idx.search('javascript OR node'); // Contains either term (default behavior)

119

120

// Wildcards

121

idx.search('java*'); // Terms starting with "java"

122

idx.search('*script'); // Terms ending with "script"

123

idx.search('*node*'); // Terms containing "node"

124

125

// Fuzzy matching

126

idx.search('javascrpt~1'); // Allow 1 character difference

127

idx.search('tutorial~2'); // Allow up to 2 character differences

128

129

// Term boosting

130

idx.search('javascript^10 tutorial'); // Boost "javascript" by factor of 10

131

idx.search('title:guide^5 content:node'); // Boost title matches

132

133

// Complex queries

134

idx.search('+(title:javascript^10 content:node) -deprecated~1');

135

```

136

137

### Programmatic Querying

138

139

Advanced programmatic query building for complex search logic.

140

141

```javascript { .api }

142

/**

143

* Programmatic query building through the query() method

144

* @param {Function} builderFunction - Function that receives a Query builder

145

*/

146

Index.prototype.query;

147

```

148

149

**Usage Examples:**

150

151

```javascript

152

// Programmatic query building

153

const results = idx.query(function (q) {

154

// Add required term

155

q.term('javascript', {

156

presence: lunr.Query.presence.REQUIRED,

157

boost: 10

158

});

159

160

// Add optional field-specific term

161

q.term('tutorial', {

162

fields: ['title'],

163

presence: lunr.Query.presence.OPTIONAL,

164

boost: 5

165

});

166

167

// Add prohibited term

168

q.term('deprecated', {

169

presence: lunr.Query.presence.PROHIBITED

170

});

171

});

172

173

// Wildcard queries

174

const wildcardResults = idx.query(function (q) {

175

q.term('java', {

176

wildcard: lunr.Query.wildcard.TRAILING, // "java*"

177

boost: 2

178

});

179

});

180

181

// Fuzzy queries with edit distance

182

const fuzzyResults = idx.query(function (q) {

183

q.term('javascrpt', {

184

editDistance: 1,

185

boost: 0.5 // Lower boost for fuzzy matches

186

});

187

});

188

```

189

190

### Index Serialization

191

192

Saving and loading indexes for persistent storage or network transmission.

193

194

```javascript { .api }

195

/**

196

* Serialize index to JSON

197

* @returns {Object} - Serialized index data

198

*/

199

Index.prototype.toJSON;

200

201

/**

202

* Load index from serialized data

203

* @param {Object} serializedIndex - Previously serialized index

204

* @returns {lunr.Index} - Reconstructed index instance

205

*/

206

Index.load;

207

```

208

209

**Usage Examples:**

210

211

```javascript

212

// Serialize index for storage

213

const idx = lunr(function () {

214

this.ref('id');

215

this.field('content');

216

this.add({ id: '1', content: 'Searchable content' });

217

});

218

219

const serialized = idx.toJSON();

220

221

// Save to localStorage

222

localStorage.setItem('searchIndex', JSON.stringify(serialized));

223

224

// Save to file (Node.js)

225

const fs = require('fs');

226

fs.writeFileSync('index.json', JSON.stringify(serialized));

227

228

// Load from storage

229

const storedData = JSON.parse(localStorage.getItem('searchIndex'));

230

const loadedIdx = lunr.Index.load(storedData);

231

232

// Load from file (Node.js)

233

const fileData = JSON.parse(fs.readFileSync('index.json', 'utf8'));

234

const fileIdx = lunr.Index.load(fileData);

235

236

// Use loaded index normally

237

const results = loadedIdx.search('searchable');

238

```

239

240

## Search Result Processing

241

242

### Result Structure

243

244

```javascript { .api }

245

/**

246

* Individual search result

247

* @typedef {Object} SearchResult

248

* @property {string} ref - Document reference identifier

249

* @property {number} score - Relevance score (0.0 to ~4.0+, higher = more relevant)

250

* @property {lunr.MatchData} matchData - Detailed match information (if available)

251

*/

252

253

/**

254

* Match data providing detailed information about matches

255

* @typedef {Object} MatchData

256

* @property {Object} metadata - Term metadata including positions and frequencies

257

*/

258

```

259

260

**Usage Examples:**

261

262

```javascript

263

const results = idx.search('javascript tutorial');

264

265

results.forEach(result => {

266

console.log(`Document: ${result.ref}`);

267

console.log(`Score: ${result.score.toFixed(3)}`);

268

269

if (result.matchData) {

270

// Access detailed match information

271

const metadata = result.matchData.metadata;

272

Object.keys(metadata).forEach(term => {

273

console.log(`Term "${term}" found in:`, Object.keys(metadata[term]));

274

});

275

}

276

});

277

```

278

279

### Result Ranking and Scoring

280

281

Understanding and working with Lunr's BM25-based scoring system.

282

283

```javascript

284

// Results are already sorted by score (highest first)

285

const results = idx.search('query terms');

286

287

// Custom result processing

288

const processedResults = results

289

.filter(result => result.score > 0.5) // Filter by minimum score

290

.slice(0, 10) // Limit to top 10

291

.map(result => ({

292

...result,

293

normalizedScore: Math.min(result.score / 2.0, 1.0) // Normalize score to 0-1

294

}));

295

296

// Group results by score ranges

297

const groupedResults = {

298

high: results.filter(r => r.score > 1.5),

299

medium: results.filter(r => r.score > 0.5 && r.score <= 1.5),

300

low: results.filter(r => r.score <= 0.5)

301

};

302

```

303

304

## Advanced Search Patterns

305

306

### Multi-field Weighted Search

307

308

```javascript

309

// Search across multiple fields with different weights

310

const results = idx.query(function (q) {

311

const searchTerm = 'javascript';

312

313

// High weight for title matches

314

q.term(searchTerm, {

315

fields: ['title'],

316

boost: 10

317

});

318

319

// Medium weight for content matches

320

q.term(searchTerm, {

321

fields: ['content'],

322

boost: 5

323

});

324

325

// Low weight for tag matches

326

q.term(searchTerm, {

327

fields: ['tags'],

328

boost: 2

329

});

330

});

331

```

332

333

### Search with Auto-complete

334

335

```javascript

336

// Implement auto-complete functionality

337

function autoComplete(partialTerm, maxResults = 5) {

338

return idx.query(function (q) {

339

// Add wildcard for prefix matching

340

q.term(partialTerm, {

341

wildcard: lunr.Query.wildcard.TRAILING,

342

boost: 10

343

});

344

345

// Also add fuzzy matching for typos

346

q.term(partialTerm, {

347

editDistance: 1,

348

boost: 5

349

});

350

}).slice(0, maxResults);

351

}

352

353

const suggestions = autoComplete('java'); // Finds "javascript", "java", etc.

354

```

355

356

### Faceted Search

357

358

```javascript

359

// Combine field restrictions for faceted search

360

function facetedSearch(query, facets = {}) {

361

return idx.query(function (q) {

362

// Main search term

363

if (query) {

364

q.term(query, { boost: 10 });

365

}

366

367

// Apply facet filters

368

Object.entries(facets).forEach(([field, value]) => {

369

q.term(value, {

370

fields: [field],

371

presence: lunr.Query.presence.REQUIRED

372

});

373

});

374

});

375

}

376

377

// Search for "tutorial" in documents tagged as "beginner" with category "javascript"

378

const facetedResults = facetedSearch('tutorial', {

379

tags: 'beginner',

380

category: 'javascript'

381

});

382

```