* 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 } = {}
)
| 1704 | * Results are ordered by name length (shorter = more likely to be the core type). |
| 1705 | */ |
| 1706 | findNodesByNameSubstring( |
| 1707 | substring: string, |
| 1708 | options: SearchOptions & { excludePrefix?: boolean } = {} |
| 1709 | ): SearchResult[] { |
| 1710 | const { kinds, languages, limit = 30, excludePrefix } = options; |
| 1711 | |
| 1712 | let sql = ` |
| 1713 | SELECT nodes.*, 1.0 as score |
| 1714 | FROM nodes |
| 1715 | WHERE name LIKE ? |
| 1716 | `; |
| 1717 | const params: (string | number)[] = [`%${substring}%`]; |
| 1718 | |
| 1719 | // Exclude prefix matches (handled by FTS-based prefix search in Step 2b) |
| 1720 | if (excludePrefix) { |
| 1721 | sql += ` AND name NOT LIKE ?`; |
| 1722 | params.push(`${substring}%`); |
| 1723 | } |
| 1724 | |
| 1725 | if (kinds && kinds.length > 0) { |
| 1726 | sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`; |
| 1727 | params.push(...kinds); |
| 1728 | } |
| 1729 | |
| 1730 | if (languages && languages.length > 0) { |
| 1731 | sql += ` AND language IN (${languages.map(() => '?').join(',')})`; |
| 1732 | params.push(...languages); |
| 1733 | } |
| 1734 | |
| 1735 | sql += ' ORDER BY length(name) ASC LIMIT ?'; |
| 1736 | params.push(limit); |
| 1737 | |
| 1738 | const rows = this.db.prepare(sql).all(...params) as (NodeRow & { score: number })[]; |
| 1739 | return rows.map((row) => ({ |
| 1740 | node: rowToNode(row), |
| 1741 | score: row.score, |
| 1742 | })); |
| 1743 | } |
| 1744 | |
| 1745 | // =========================================================================== |
| 1746 | // Edge Operations |
no test coverage detected