242 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Go
		
	
	
	
| // Copyright (C) INFINI Labs & INFINI LIMITED.
 | |
| //
 | |
| // The INFINI Console is offered under the GNU Affero General Public License v3.0
 | |
| // and as commercial software.
 | |
| //
 | |
| // For commercial licensing, contact us at:
 | |
| //   - Website: infinilabs.com
 | |
| //   - Email: hello@infini.ltd
 | |
| //
 | |
| // Open Source licensed under AGPL V3:
 | |
| // This program is free software: you can redistribute it and/or modify
 | |
| // it under the terms of the GNU Affero General Public License as published by
 | |
| // the Free Software Foundation, either version 3 of the License, or
 | |
| // (at your option) any later version.
 | |
| //
 | |
| // This program is distributed in the hope that it will be useful,
 | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | |
| // GNU Affero General Public License for more details.
 | |
| //
 | |
| // You should have received a copy of the GNU Affero General Public License
 | |
| // along with this program. If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| package index_management
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"strings"
 | |
| 
 | |
| 	httprouter "infini.sh/framework/core/api/router"
 | |
| 	"infini.sh/framework/core/elastic"
 | |
| 	"infini.sh/framework/core/util"
 | |
| )
 | |
| 
 | |
| type docReqBody struct {
 | |
| 	From          int    `json:"from"`
 | |
| 	Size          int    `json:"size"`
 | |
| 	Filter        string `json:"filter"`
 | |
| 	Cluster       string `json:"cluster"`
 | |
| 	Keyword       string `json:"keyword"`
 | |
| 	Sort          string `json:"sort"`
 | |
| 	SortDirection string `json:"sort_direction"`
 | |
| }
 | |
| 
 | |
| func (handler APIHandler) HandleAddDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
 | |
| 	targetClusterID := ps.ByName("id")
 | |
| 	client := elastic.GetClient(targetClusterID)
 | |
| 	reqBody := map[string]interface{}{}
 | |
| 	resBody := newResponseBody()
 | |
| 	err := handler.DecodeJSON(req, &reqBody)
 | |
| 	if err != nil {
 | |
| 		resBody["error"] = err.Error()
 | |
| 		handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	indexName := ps.ByName("index")
 | |
| 	docID := ps.ByName("docId")
 | |
| 	if strings.Trim(docID, "/") == "" {
 | |
| 		docID = util.GetUUID()
 | |
| 	}
 | |
| 	docType := handler.GetParameter(req, "_type")
 | |
| 	insertRes, err := client.Index(indexName, docType, docID, reqBody, "wait_for")
 | |
| 	if err != nil {
 | |
| 		resBody["error"] = err
 | |
| 		handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	reqBody["_id"] = docID
 | |
| 	resBody["result"] = insertRes.Result
 | |
| 	handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| }
 | |
| 
 | |
| func (handler APIHandler) HandleUpdateDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
 | |
| 	targetClusterID := ps.ByName("id")
 | |
| 	client := elastic.GetClient(targetClusterID)
 | |
| 	resBody := newResponseBody()
 | |
| 	if client == nil {
 | |
| 		resBody["error"] = "can not found target cluster"
 | |
| 		handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	reqBody := map[string]interface{}{}
 | |
| 
 | |
| 	err := handler.DecodeJSON(req, &reqBody)
 | |
| 	if err != nil {
 | |
| 		resBody["error"] = err.Error()
 | |
| 		handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	indexName := ps.ByName("index")
 | |
| 	docID := ps.ByName("docId")
 | |
| 	typ := handler.GetParameter(req, "_type")
 | |
| 	isNew := handler.GetParameter(req, "is_new")
 | |
| 	if isNew == "1" {
 | |
| 		getRes, err := client.Get(indexName, typ, docID)
 | |
| 		if err != nil {
 | |
| 			resBody["error"] = err.Error()
 | |
| 			handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 			return
 | |
| 		}
 | |
| 		if getRes.Found {
 | |
| 			resBody["error"] = "doc id already exists"
 | |
| 			handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	insertRes, err := client.Index(indexName, typ, docID, reqBody, "wait_for")
 | |
| 	if err != nil {
 | |
| 		resBody["error"] = err.Error()
 | |
| 		handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	resBody["_source"] = reqBody
 | |
| 	resBody["_id"] = docID
 | |
| 	resBody["result"] = insertRes.Result
 | |
| 	handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| }
 | |
| 
 | |
| func (handler APIHandler) HandleDeleteDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
 | |
| 	targetClusterID := ps.ByName("id")
 | |
| 	client := elastic.GetClient(targetClusterID)
 | |
| 	resBody := newResponseBody()
 | |
| 	if client == nil {
 | |
| 		resBody["error"] = "can not found target cluster"
 | |
| 		handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	indexName := ps.ByName("index")
 | |
| 	docID := ps.ByName("docId")
 | |
| 	typ := handler.GetParameter(req, "_type")
 | |
| 	delRes, err := client.Delete(indexName, typ, docID, "wait_for")
 | |
| 	if err != nil {
 | |
| 		resBody["error"] = err.Error()
 | |
| 		handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	resBody["result"] = delRes.Result
 | |
| 	handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| }
 | |
| 
 | |
| func (handler APIHandler) HandleSearchDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
 | |
| 	targetClusterID := ps.ByName("id")
 | |
| 	client := elastic.GetClient(targetClusterID)
 | |
| 	reqBody := docReqBody{}
 | |
| 	resResult := newResponseBody()
 | |
| 	err := handler.DecodeJSON(req, &reqBody)
 | |
| 	if err != nil {
 | |
| 		resResult["status"] = false
 | |
| 		resResult["error"] = err.Error()
 | |
| 		handler.WriteJSON(w, resResult, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	indexName := ps.ByName("index")
 | |
| 	var (
 | |
| 		sort = ""
 | |
| 	)
 | |
| 	if reqBody.From < 0 {
 | |
| 		reqBody.From = 0
 | |
| 	}
 | |
| 	if reqBody.Size <= 0 {
 | |
| 		reqBody.Size = 10
 | |
| 	}
 | |
| 	filter := `{"match_all": {}}`
 | |
| 	if reqBody.Keyword != "" {
 | |
| 		filter = fmt.Sprintf(`{"query_string":{"query":"%s"}}`, reqBody.Keyword)
 | |
| 	}
 | |
| 	if reqBody.Filter != "" {
 | |
| 		filter = reqBody.Filter
 | |
| 	}
 | |
| 	if sortField := strings.Trim(reqBody.Sort, " "); sortField != "" {
 | |
| 		sortDirection := reqBody.SortDirection
 | |
| 		if sortDirection != "desc" {
 | |
| 			sortDirection = "asc"
 | |
| 		}
 | |
| 		sort = fmt.Sprintf(`"%s":{"order":"%s"}`, sortField, sortDirection)
 | |
| 	}
 | |
| 	query := fmt.Sprintf(`{"from":%d, "size": %d, "query": %s, "sort": [{%s}]}`, reqBody.From, reqBody.Size, filter, sort)
 | |
| 	//fmt.Println(indexName, query)
 | |
| 	var reqBytes = []byte(query)
 | |
| 	resp, err := client.SearchWithRawQueryDSL(indexName, reqBytes)
 | |
| 	if err != nil {
 | |
| 		resResult["status"] = false
 | |
| 		resResult["error"] = err.Error()
 | |
| 		handler.WriteJSON(w, resResult, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	//result := formatESSearchResult(resp)
 | |
| 
 | |
| 	resResult["payload"] = resp
 | |
| 
 | |
| 	handler.WriteJSON(w, resResult, http.StatusOK)
 | |
| }
 | |
| 
 | |
| func (handler APIHandler) ValidateDocIDAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
 | |
| 	targetClusterID := ps.ByName("id")
 | |
| 	client := elastic.GetClient(targetClusterID)
 | |
| 	resBody := util.MapStr{}
 | |
| 	if client != nil {
 | |
| 		resBody["error"] = "cluster not found"
 | |
| 		handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	var (
 | |
| 		index = handler.GetParameter(req, "index")
 | |
| 		docID = handler.GetParameter(req, "doc_id")
 | |
| 		typ   = handler.GetParameter(req, "type")
 | |
| 	)
 | |
| 	getRes, err := client.Get(index, typ, docID)
 | |
| 	if err != nil {
 | |
| 		resBody["error"] = err
 | |
| 		handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| 		return
 | |
| 	}
 | |
| 	resBody["found"] = getRes.Found
 | |
| 	handler.WriteJSON(w, resBody, http.StatusOK)
 | |
| }
 | |
| 
 | |
| func formatESSearchResult(esResp *elastic.SearchResponse) map[string]interface{} {
 | |
| 	total := esResp.Hits.Total
 | |
| 	if len(esResp.Hits.Hits) == 0 {
 | |
| 		return map[string]interface{}{
 | |
| 			"total": total,
 | |
| 			"data":  nil,
 | |
| 		}
 | |
| 	}
 | |
| 	dataArr := make([]interface{}, 0, len(esResp.Hits.Hits))
 | |
| 	for _, hit := range esResp.Hits.Hits {
 | |
| 		if _, ok := hit.Source["id"]; !ok {
 | |
| 			hit.Source["id"] = hit.ID
 | |
| 		}
 | |
| 		hit.Source["_index"] = hit.Index
 | |
| 		dataArr = append(dataArr, hit.Source)
 | |
| 	}
 | |
| 	return map[string]interface{}{
 | |
| 		"total": total,
 | |
| 		"data":  dataArr,
 | |
| 	}
 | |
| }
 |