package cmd import ( "fmt" "os" "strings" "github.com/aisim/kb-cli/internal/index" "github.com/aisim/kb-cli/internal/search" "github.com/aisim/kb-cli/internal/output" "github.com/spf13/cobra" ) var ( expanded []string symptom []string topN int jsonOut bool withContent bool withLinks bool ) var searchCmd = &cobra.Command{ Use: "search [keywords...]", Short: "搜索知识库", Long: `# search - 搜索 kb-cli search <关键词> [--top N] [--expanded <词>] [--symptom <词>] [--with-content] [--with-links] [--json] # 搜索知识库,支持关键词、扩展词、症状词`, Args: cobra.MinimumNArgs(1), RunE: runSearch, } func init() { rootCmd.AddCommand(searchCmd) searchCmd.Flags().StringSliceVar(&expanded, "expanded", nil, "扩展词(提升相关实体权重)") searchCmd.Flags().StringSliceVar(&symptom, "symptom", nil, "症状词(针对具体症状)") searchCmd.Flags().IntVar(&topN, "top", 10, "返回前 N 条结果") searchCmd.Flags().BoolVar(&jsonOut, "json", false, "JSON 格式输出") searchCmd.Flags().BoolVar(&withContent, "with-content", false, "返回完整文件内容") searchCmd.Flags().BoolVar(&withLinks, "with-links", false, "显示关联文档链接") // 参数不足时显示 help searchCmd.SetUsageTemplate(searchCmd.Long) } func runSearch(cmd *cobra.Command, args []string) error { // 打开索引 store, err := index.Open(dbPath) if err != nil { return fmt.Errorf("打开索引失败: %w", err) } defer store.Close() // 检查是否需要重建索引 needsRebuild, commit, err := index.NeedsRebuild(store, vaultPath) if err != nil { return fmt.Errorf("检查索引状态失败: %w", err) } if needsRebuild { fmt.Fprintln(os.Stderr, "索引过期,正在重建...") if err := rebuildIndex(store, commit); err != nil { return fmt.Errorf("重建索引失败: %w", err) } } // 合并所有关键词(支持空格分隔和引号分隔) var allKeywords []string for _, arg := range args { // 如果参数包含空格,按空格分割 parts := strings.Fields(arg) allKeywords = append(allKeywords, parts...) } if len(allKeywords) == 0 { return fmt.Errorf("请提供至少一个关键词") } // 执行搜索 opts := search.SearchOptions{ Expanded: expanded, Symptom: symptom, TopN: topN, WithContent: withContent, WithLinks: withLinks, } results, err := search.Search(store, allKeywords, opts) if err != nil { return fmt.Errorf("搜索失败: %w", err) } // 输出结果 if jsonOut { jsonStr, err := output.FormatJSON(results) if err != nil { return err } fmt.Println(jsonStr) } else { fmt.Print(output.FormatTable(results)) } return nil }