yangdx commited on
Commit
dcae38a
·
1 Parent(s): 0a76061

Limit the search scope to labels in the current subgraph

Browse files

- Decouple datasource label selection from the search input field
- Improve label selection handling logic

lightrag_webui/src/components/graph/GraphLabels.tsx CHANGED
@@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next'
9
  const GraphLabels = () => {
10
  const { t } = useTranslation()
11
  const label = useSettingsStore.use.queryLabel()
12
- const graphLabels = useGraphStore.use.graphLabels()
13
 
14
  const getSearchEngine = useCallback(() => {
15
  // Create search engine
@@ -26,14 +26,14 @@ const GraphLabels = () => {
26
  })
27
 
28
  // Add documents
29
- const documents = graphLabels.map((str, index) => ({ id: index, value: str }))
30
  searchEngine.addAll(documents)
31
 
32
  return {
33
- labels: graphLabels,
34
  searchEngine
35
  }
36
- }, [graphLabels])
37
 
38
  const fetchData = useCallback(
39
  async (query?: string): Promise<string[]> => {
@@ -47,27 +47,11 @@ const GraphLabels = () => {
47
 
48
  return result.length <= labelListLimit
49
  ? result
50
- : [...result.slice(0, labelListLimit), t('graphLabels.andOthers', { count: result.length - labelListLimit })]
51
  },
52
  [getSearchEngine, t]
53
  )
54
 
55
- const setQueryLabel = useCallback((newLabel: string) => {
56
- if (newLabel.startsWith('And ') && newLabel.endsWith(' others')) return
57
-
58
- const currentLabel = useSettingsStore.getState().queryLabel
59
-
60
- if (newLabel === '*' && currentLabel === '*') {
61
- // When reselecting '*', just set it again to trigger a new fetch
62
- useSettingsStore.getState().setQueryLabel('*')
63
- } else if (newLabel === currentLabel && newLabel !== '*') {
64
- // When selecting the same label (except '*'), switch to '*'
65
- useSettingsStore.getState().setQueryLabel('*')
66
- } else {
67
- useSettingsStore.getState().setQueryLabel(newLabel)
68
- }
69
- }, [])
70
-
71
  return (
72
  <AsyncSelect<string>
73
  className="ml-2"
@@ -81,8 +65,20 @@ const GraphLabels = () => {
81
  notFound={<div className="py-6 text-center text-sm">No labels found</div>}
82
  label={t('graphPanel.graphLabels.label')}
83
  placeholder={t('graphPanel.graphLabels.placeholder')}
84
- value={label !== null ? label : ''}
85
- onChange={setQueryLabel}
 
 
 
 
 
 
 
 
 
 
 
 
86
  clearable={false} // Prevent clearing value on reselect
87
  />
88
  )
 
9
  const GraphLabels = () => {
10
  const { t } = useTranslation()
11
  const label = useSettingsStore.use.queryLabel()
12
+ const allDatabaseLabels = useGraphStore.use.allDatabaseLabels()
13
 
14
  const getSearchEngine = useCallback(() => {
15
  // Create search engine
 
26
  })
27
 
28
  // Add documents
29
+ const documents = allDatabaseLabels.map((str, index) => ({ id: index, value: str }))
30
  searchEngine.addAll(documents)
31
 
32
  return {
33
+ labels: allDatabaseLabels,
34
  searchEngine
35
  }
36
+ }, [allDatabaseLabels])
37
 
38
  const fetchData = useCallback(
39
  async (query?: string): Promise<string[]> => {
 
47
 
48
  return result.length <= labelListLimit
49
  ? result
50
+ : [...result.slice(0, labelListLimit), '...']
51
  },
52
  [getSearchEngine, t]
53
  )
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  return (
56
  <AsyncSelect<string>
57
  className="ml-2"
 
65
  notFound={<div className="py-6 text-center text-sm">No labels found</div>}
66
  label={t('graphPanel.graphLabels.label')}
67
  placeholder={t('graphPanel.graphLabels.placeholder')}
68
+ value={label !== null ? label : '*'}
69
+ onChange={(newLabel) => {
70
+ const currentLabel = useSettingsStore.getState().queryLabel
71
+
72
+ if (newLabel === '...') {
73
+ newLabel = '*'
74
+ }
75
+ if (newLabel === currentLabel && newLabel !== '*') {
76
+ // 选择相同标签时切换到'*'
77
+ useSettingsStore.getState().setQueryLabel('*')
78
+ } else {
79
+ useSettingsStore.getState().setQueryLabel(newLabel)
80
+ }
81
+ }}
82
  clearable={false} // Prevent clearing value on reselect
83
  />
84
  )
lightrag_webui/src/hooks/useLightragGraph.tsx CHANGED
@@ -169,6 +169,11 @@ const useLightrangeGraph = () => {
169
  const minDegree = useSettingsStore.use.graphMinDegree()
170
  const isFetching = useGraphStore.use.isFetching()
171
 
 
 
 
 
 
172
  // Use ref to track fetch status
173
  const fetchStatusRef = useRef<Record<string, boolean>>({});
174
 
@@ -222,7 +227,7 @@ const useLightrangeGraph = () => {
222
  state.setSigmaGraph(newSigmaGraph)
223
  state.setRawGraph(data)
224
 
225
- // Extract labels from graph data
226
  if (data) {
227
  const labelSet = new Set<string>();
228
  for (const node of data.nodes) {
@@ -241,6 +246,9 @@ const useLightrangeGraph = () => {
241
  // Ensure * is there eventhough there is no graph data
242
  state.setGraphLabels(['*']);
243
  }
 
 
 
244
  if (!data) {
245
  // If data is invalid, remove the fetch flag to allow retry
246
  delete fetchStatusRef.current[fetchKey];
 
169
  const minDegree = useSettingsStore.use.graphMinDegree()
170
  const isFetching = useGraphStore.use.isFetching()
171
 
172
+ // Fetch all database labels on mount
173
+ useEffect(() => {
174
+ useGraphStore.getState().fetchAllDatabaseLabels()
175
+ }, [])
176
+
177
  // Use ref to track fetch status
178
  const fetchStatusRef = useRef<Record<string, boolean>>({});
179
 
 
227
  state.setSigmaGraph(newSigmaGraph)
228
  state.setRawGraph(data)
229
 
230
+ // Extract labels from current graph data
231
  if (data) {
232
  const labelSet = new Set<string>();
233
  for (const node of data.nodes) {
 
246
  // Ensure * is there eventhough there is no graph data
247
  state.setGraphLabels(['*']);
248
  }
249
+
250
+ // Fetch all database labels after graph update
251
+ state.fetchAllDatabaseLabels();
252
  if (!data) {
253
  // If data is invalid, remove the fetch flag to allow retry
254
  delete fetchStatusRef.current[fetchKey];
lightrag_webui/src/stores/graph.ts CHANGED
@@ -1,6 +1,7 @@
1
  import { create } from 'zustand'
2
  import { createSelectors } from '@/lib/utils'
3
  import { DirectedGraph } from 'graphology'
 
4
 
5
  export type RawNodeType = {
6
  id: string
@@ -66,6 +67,7 @@ interface GraphState {
66
  rawGraph: RawGraph | null
67
  sigmaGraph: DirectedGraph | null
68
  graphLabels: string[]
 
69
 
70
  moveToSelectedNode: boolean
71
  isFetching: boolean
@@ -82,6 +84,8 @@ interface GraphState {
82
  setRawGraph: (rawGraph: RawGraph | null) => void
83
  setSigmaGraph: (sigmaGraph: DirectedGraph | null) => void
84
  setGraphLabels: (labels: string[]) => void
 
 
85
  setIsFetching: (isFetching: boolean) => void
86
  }
87
 
@@ -97,6 +101,7 @@ const useGraphStoreBase = create<GraphState>()((set) => ({
97
  rawGraph: null,
98
  sigmaGraph: null,
99
  graphLabels: ['*'],
 
100
 
101
  setIsFetching: (isFetching: boolean) => set({ isFetching }),
102
  setSelectedNode: (nodeId: string | null, moveToSelectedNode?: boolean) =>
@@ -132,6 +137,18 @@ const useGraphStoreBase = create<GraphState>()((set) => ({
132
 
133
  setGraphLabels: (labels: string[]) => set({ graphLabels: labels }),
134
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  setMoveToSelectedNode: (moveToSelectedNode?: boolean) => set({ moveToSelectedNode })
136
  }))
137
 
 
1
  import { create } from 'zustand'
2
  import { createSelectors } from '@/lib/utils'
3
  import { DirectedGraph } from 'graphology'
4
+ import { getGraphLabels } from '@/api/lightrag'
5
 
6
  export type RawNodeType = {
7
  id: string
 
67
  rawGraph: RawGraph | null
68
  sigmaGraph: DirectedGraph | null
69
  graphLabels: string[]
70
+ allDatabaseLabels: string[]
71
 
72
  moveToSelectedNode: boolean
73
  isFetching: boolean
 
84
  setRawGraph: (rawGraph: RawGraph | null) => void
85
  setSigmaGraph: (sigmaGraph: DirectedGraph | null) => void
86
  setGraphLabels: (labels: string[]) => void
87
+ setAllDatabaseLabels: (labels: string[]) => void
88
+ fetchAllDatabaseLabels: () => Promise<void>
89
  setIsFetching: (isFetching: boolean) => void
90
  }
91
 
 
101
  rawGraph: null,
102
  sigmaGraph: null,
103
  graphLabels: ['*'],
104
+ allDatabaseLabels: ['*'],
105
 
106
  setIsFetching: (isFetching: boolean) => set({ isFetching }),
107
  setSelectedNode: (nodeId: string | null, moveToSelectedNode?: boolean) =>
 
137
 
138
  setGraphLabels: (labels: string[]) => set({ graphLabels: labels }),
139
 
140
+ setAllDatabaseLabels: (labels: string[]) => set({ allDatabaseLabels: labels }),
141
+
142
+ fetchAllDatabaseLabels: async () => {
143
+ try {
144
+ const labels = await getGraphLabels();
145
+ set({ allDatabaseLabels: ['*', ...labels] });
146
+ } catch (error) {
147
+ console.error('Failed to fetch all database labels:', error);
148
+ set({ allDatabaseLabels: ['*'] });
149
+ }
150
+ },
151
+
152
  setMoveToSelectedNode: (moveToSelectedNode?: boolean) => set({ moveToSelectedNode })
153
  }))
154