* Find nodes whose name contains a substring (LIKE-based). * Useful for CamelCase-part matching where FTS fails because * e.g. "TransportSearchAction" is one FTS token, not matchable by "Search"*. * * Results are ordered by name length (shorter = more likely to be the core type).
(
substring: string,
options: SearchOptions & { excludePrefix?: boolean } = {}
)
| 1598 | * Results are ordered by name length (shorter = more likely to be the core type). |
| 1599 | */ |
| 1600 | findNodesByNameSubstring( |
| 1601 | substring: string, |
| 1602 | options: SearchOptions & { excludePrefix?: boolean } = {} |
| 1603 | ): SearchResult[] { |
| 1604 | const { kinds, languages, limit = 30, excludePrefix } = options; |
| 1605 | |
| 1606 | let sql = ` |
| 1607 | SELECT nodes.*, 1.0 as score |
| 1608 | FROM nodes |
| 1609 | WHERE name LIKE ? |
| 1610 | `; |
| 1611 | const params: (string | number)[] = [`%${substring}%`]; |
| 1612 | |
| 1613 | // Exclude prefix matches (handled by FTS-based prefix search in Step 2b) |
| 1614 | if (excludePrefix) { |
| 1615 | sql += ` AND name NOT LIKE ?`; |
| 1616 | params.push(`${substring}%`); |
| 1617 | } |
| 1618 | |
| 1619 | if (kinds && kinds.length > 0) { |
| 1620 | sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`; |
| 1621 | params.push(...kinds); |
| 1622 | } |
| 1623 | |
| 1624 | if (languages && languages.length > 0) { |
| 1625 | sql += ` AND language IN (${languages.map(() => '?').join(',')})`; |
| 1626 | params.push(...languages); |
| 1627 | } |
| 1628 | |
| 1629 | sql += ' ORDER BY length(name) ASC LIMIT ?'; |
| 1630 | params.push(limit); |
| 1631 | |
| 1632 | const rows = this.db.prepare(sql).all(...params) as (NodeRow & { score: number })[]; |
| 1633 | return rows.map((row) => ({ |
| 1634 | node: rowToNode(row), |
| 1635 | score: row.score, |
| 1636 | })); |
| 1637 | } |
| 1638 | |
| 1639 | // =========================================================================== |
| 1640 | // Edge Operations |
no test coverage detected