Procházet zdrojové kódy

支持建议来源

visuddhinanda před 6 měsíci
rodič
revize
f318966be6
1 změnil soubory, kde provedl 138 přidání a 49 odebrání
  1. 138 49
      api-v8/app/Http/Controllers/SearchSuggestController.php

+ 138 - 49
api-v8/app/Http/Controllers/SearchSuggestController.php

@@ -1,39 +1,44 @@
 <?php
-
+// api-v8/app/Http/Controllers/SearchSuggestController.php
 namespace App\Http\Controllers;
 
 use App\Http\Controllers\Controller;
 use Illuminate\Http\Request;
 use App\Services\OpenSearchService;
 
-
 /**
- * 返回示例
- * 请求:GET /api/v2/suggest?q=慈&type=term&limit=5
+ * 搜索自动建议控制器
+ *
+ * 返回示例:
+ *
+ * 请求:GET /api/v2/suggest?q=dhamma&fields=title,content&limit=10
+ *
  * 返回:
  * {
-  "success": true,
-  "data": {
-    "suggestions": [
-      {
-        "text": "慈悲",
-        "resource_type": "translation",
-        "language": "zh-Hans"
-      },
-      {
-        "text": "mettā",
-        "resource_type": "origin_text",
-        "language": "pali"
-      },
-      {
-        "text": "compassion",
-        "resource_type": "translation",
-        "language": "en-US"
-      }
-    ]
-  }
-}
-
+ *   "success": true,
+ *   "data": {
+ *     "query": "dhamma",
+ *     "suggestions": [
+ *       {
+ *         "text": "dhammapada",
+ *         "source": "title",
+ *         "score": 5.2,
+ *         "resource_type": "sutta",
+ *         "language": "pali",
+ *         "doc_id": "doc_123"
+ *       },
+ *       {
+ *         "text": "dhammapadā",
+ *         "source": "content",
+ *         "score": 4.8,
+ *         "resource_type": "commentary",
+ *         "language": "pali",
+ *         "doc_id": "doc_456"
+ *       }
+ *     ],
+ *     "total": 2
+ *   }
+ * }
  */
 class SearchSuggestController extends Controller
 {
@@ -50,56 +55,140 @@ class SearchSuggestController extends Controller
     }
 
     /**
-     * Display a listing of suggestions.
+     * # 1. 查询所有字段(默认)
+GET /api/v2/suggest?q=dhamma&limit=10
+
+# 2. 只查询标题
+GET /api/v2/suggest?q=dhamma&fields=title&limit=10
+
+# 3. 查询标题和内容
+GET /api/v2/suggest?q=dhamma&fields=title,content&limit=10
+
+# 4. 查询页面引用,带语言过滤
+GET /api/v2/suggest?q=M.1&fields=page_refs&language=pali&limit=5
+
+# 5. 数组形式传递多个字段
+GET /api/v2/suggest?q=dhamma&fields[]=title&fields[]=content&limit=10
+     */
+    /**
+     * 自动建议接口
      *
-     * 自动建议接口,基于 OpenSearch completion suggester。
-     * 支持术语、巴利罗马化拼写、页码等建议。
+     * 基于 OpenSearch completion suggester,支持从不同字段获取建议。
      *
      * @param  \Illuminate\Http\Request  $request
      *   - q (string): 输入的部分文本(必填)
-     *   - type (string): 建议类型,可选值 term|pali_romanized|page_ref,默认 term
-     *   - language (string): 语言过滤,可选
-     *   - limit (int): 返回数量,默认 10,最大 50
+     *   - fields (string|array): 要查询的字段,可选值:
+     *       - 不传:查询所有字段 (title, content, page_refs)
+     *       - 单个字段:'title' | 'content' | 'page_refs'
+     *       - 多个字段:'title,content' 或 ['title', 'content']
+     *   - language (string): 语言过滤,可选(如:pali, zh, en)
+     *   - limit (int): 每个字段返回的建议数量,默认 10,最大 50
      *
      * @return \Illuminate\Http\JsonResponse
      */
     public function index(Request $request)
     {
-        $query    = $request->input('q', '');
-        $type     = $request->input('type', 'term');
-        $language = $request->input('language');
-        $limit    = min(50, (int) $request->input('limit', 10));
-
+        // 验证必填参数
+        $query = $request->input('q', '');
         if (empty($query)) {
             return response()->json([
                 'success' => false,
-                'error'   => '缺少参数 q'
+                'error'   => '缺少参数 q(查询文本)'
             ], 400);
         }
 
+        // 解析 fields 参数
+        $fields = $this->parseFields($request->input('fields'));
+
+        // 获取其他参数
+        $language = $request->input('language', null);
+        $limit = min(50, max(1, (int) $request->input('limit', 10)));
+
         try {
-            $rawSuggestions = $this->searchService->suggest($query, $type, $language, $limit);
+            // 调用搜索服务
+            $rawSuggestions = $this->searchService->suggest(
+                $query,
+                $fields,
+                $language,
+                $limit
+            );
 
-            // 格式化返回结果:包含 text + resource_type + language
-            $suggestions = collect($rawSuggestions)->map(function ($item) {
-                return [
-                    'text'          => $item['text'] ?? '',
-                    'resource_type' => $item['resource_type'] ?? null,
-                    'language'      => $item['language'] ?? null,
-                ];
-            })->all();
+            // 格式化返回结果
+            $suggestions = $this->formatSuggestions($rawSuggestions);
 
             return response()->json([
                 'success' => true,
                 'data'    => [
-                    'suggestions' => $suggestions
+                    'query'       => $query,
+                    'suggestions' => $suggestions,
+                    'total'       => count($suggestions)
                 ]
             ]);
+        } catch (\InvalidArgumentException $e) {
+            return response()->json([
+                'success' => false,
+                'error'   => '无效的字段参数:' . $e->getMessage(),
+                'hint'    => '有效的字段值:title, content, page_refs'
+            ], 400);
         } catch (\Exception $e) {
             return response()->json([
                 'success' => false,
-                'error'   => $e->getMessage(),
+                'error'   => '搜索建议失败:' . $e->getMessage(),
             ], 500);
         }
     }
+
+    /**
+     * 解析 fields 参数
+     *
+     * @param  mixed  $fields
+     * @return string|array|null
+     */
+    protected function parseFields($fields)
+    {
+        if ($fields === null) {
+            return null;  // 查询所有字段
+        }
+
+        if (is_string($fields)) {
+            // 如果是逗号分隔的字符串,转换为数组
+            if (strpos($fields, ',') !== false) {
+                $fieldsArray = array_map('trim', explode(',', $fields));
+                return $fieldsArray;
+            }
+            // 单个字段
+            return $fields;
+        }
+
+        if (is_array($fields)) {
+            return $fields;
+        }
+
+        return null;
+    }
+
+    /**
+     * 格式化建议结果
+     *
+     * @param  array  $rawSuggestions
+     * @return array
+     */
+    protected function formatSuggestions(array $rawSuggestions): array
+    {
+        return collect($rawSuggestions)->map(function ($item) {
+            $docSource = $item['doc_source'] ?? [];
+
+            return [
+                'text'          => $item['text'] ?? '',
+                'source'        => $item['source'] ?? null,
+                'score'         => round($item['score'] ?? 0, 2),
+                'resource_type' => $docSource['resource_type'] ?? null,
+                'language'      => $docSource['language'] ?? null,
+                'doc_id'        => $item['doc_id'] ?? null,
+                // 可选:添加更多元数据
+                'category'      => $docSource['category'] ?? null,
+                'granularity'   => $docSource['granularity'] ?? null,
+            ];
+        })->all();
+    }
 }