feat: Improve node search with fuzzy matching and ranking#5370
feat: Improve node search with fuzzy matching and ranking#5370HenryHengZJ merged 2 commits intoFlowiseAI:mainfrom
Conversation
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
WalkthroughAdded fuzzy search to AddNodes: implemented fuzzyScore and scoreAndSortNodes, replaced substring filtering with similarity scoring in both Agent and non-Agent flows, updated filterSearch to use new scoring, and renamed prop Changes
Sequence DiagramsequenceDiagram
participant User
participant AddNodes
participant getSearchedNodes
participant scoreAndSortNodes
participant fuzzyScore
participant UI
User->>AddNodes: type search term (filterSearch)
AddNodes->>getSearchedNodes: request with searchValue, nodes
rect rgb(200,220,255)
Note over getSearchedNodes: agent/non-agent path chooses node subset
getSearchedNodes->>scoreAndSortNodes: nodes subset, searchValue
end
rect rgb(220,200,255)
Note over scoreAndSortNodes: score & sort execution
loop for each node field (name,label,category)
scoreAndSortNodes->>fuzzyScore: searchTerm, fieldValue
fuzzyScore-->>scoreAndSortNodes: score
end
scoreAndSortNodes->>scoreAndSortNodes: keep score>0, sort desc
end
scoreAndSortNodes-->>getSearchedNodes: scored nodes
getSearchedNodes-->>AddNodes: results
AddNodes->>UI: render grouped results
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧬 Code graph analysis (1)packages/ui/src/views/canvas/AddNodes.jsx (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
🔇 Additional comments (4)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
packages/ui/src/views/canvas/AddNodes.jsx (4)
190-213: Guard inputs, trim once, and avoidnodesshadowing in scoreAndSortNodes.Pre-trim the query, short‑circuit on empty, and rename the param to avoid confusion with state
nodes.- const scoreAndSortNodes = (nodes, searchValue) => { - // Return all nodes unsorted if search is empty - if (!searchValue || searchValue.trim() === '') { - return nodes - } + const scoreAndSortNodes = (candidateNodes, searchValue) => { + const q = (searchValue ?? '').trim() + if (!q) return candidateNodes @@ - const nodesWithScores = nodes.map((nd) => { - const nameScore = fuzzyScore(searchValue, nd.name) - const labelScore = fuzzyScore(searchValue, nd.label) - const categoryScore = fuzzyScore(searchValue, nd.category) * 0.5 // Lower weight for category + const nodesWithScores = candidateNodes.map((nd) => { + const nameScore = fuzzyScore(q, nd?.name) + const labelScore = fuzzyScore(q, nd?.label) + const categoryScore = fuzzyScore(q, nd?.category) * 0.5 // Lower weight for category const maxScore = Math.max(nameScore, labelScore, categoryScore) return { node: nd, score: maxScore } })
214-219: Avoid shadowing statenodesin getSearchedNodes (agent canvas branch).Rename local
nodesfor clarity.- if (isAgentCanvas) { - const nodes = nodesData.filter((nd) => !blacklistCategoriesForAgentCanvas.includes(nd.category)) - nodes.push(...addException()) - return scoreAndSortNodes(nodes, value) - } + if (isAgentCanvas) { + const filteredNodes = nodesData.filter((nd) => !blacklistCategoriesForAgentCanvas.includes(nd.category)) + filteredNodes.push(...addException()) + return scoreAndSortNodes(filteredNodes, value) + }
220-228: Same rename for non‑agent branch; minor readability.- let nodes = nodesData.filter((nd) => nd.category !== 'Multi Agents' && nd.category !== 'Sequential Agents') + let filteredNodes = nodesData.filter((nd) => nd.category !== 'Multi Agents' && nd.category !== 'Sequential Agents') @@ - nodes = nodes.filter((nd) => !nodeNames.includes(nd.name)) + filteredNodes = filteredNodes.filter((nd) => !nodeNames.includes(nd.name)) } - - return scoreAndSortNodes(nodes, value) + return scoreAndSortNodes(filteredNodes, value)
230-242: Debounce should clear pending timers to avoid stale updates.Using bare
setTimeoutcan apply older results after newer keystrokes and leaks on unmount. Replace with a cancellable debounce.- const filterSearch = (value, newTabValue) => { - setSearchValue(value) - setTimeout(() => { + const debounceRef = useRef() + const filterSearch = (value, newTabValue) => { + setSearchValue(value) + if (debounceRef.current) clearTimeout(debounceRef.current) + debounceRef.current = setTimeout(() => { if (value) { const returnData = getSearchedNodes(value) groupByCategory(returnData, newTabValue ?? tabValue, true) scrollTop() } else if (value === '') { groupByCategory(nodesData, newTabValue ?? tabValue) scrollTop() } - }, 500) + }, 500) }Optionally, add
useEffect(() => () => debounceRef.current && clearTimeout(debounceRef.current), [])for cleanup.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/ui/src/views/canvas/AddNodes.jsx(2 hunks)
🔇 Additional comments (1)
packages/ui/src/views/canvas/AddNodes.jsx (1)
399-402: GuardonFlowGeneratedbefore calling it.The prop is optional in PropTypes (line 754:
PropTypes.funcwithout.isRequired), but called unconditionally at line 401, which will throw if omitted. Apply the guard:- onFlowGenerated() + if (typeof onFlowGenerated === 'function') onFlowGenerated()Note: The old prop name
onFlowGeneratis not found anywhere in the codebase, so the back-compat alias suggestion is unnecessary. The rename has been fully completed. Consider marking the prop as required in PropTypes if it's truly mandatory.
Problem:
When searching for nodes in the Agent/chat canvases, the searches are annoyingly strict. I added a fuzzy search, so that smaller spelling mistakes are accepted. Results are sorted by how good the match is.
Two Types of Matching
How Nodes Are Ranked
Each node is scored on three fields:
The highest score from these three wins.
Penalties
Real Examples
Searching "conv":
Searching "llm":
Summary by CodeRabbit
New Features
Chores