1// Copyright 2013 Matthew Baird
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//     http://www.apache.org/licenses/LICENSE-2.0
6// Unless required by applicable law or agreed to in writing, software
7// distributed under the License is distributed on an "AS IS" BASIS,
8// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9// See the License for the specific language governing permissions and
10// limitations under the License.
11
12package elastigo
13
14import (
15	"encoding/json"
16	"errors"
17	"fmt"
18	"net/url"
19	"strconv"
20)
21
22// Index adds or updates a typed JSON document in a specific index, making it searchable, creating an index
23// if it did not exist.
24// if id is omited, op_type 'create' will be passed and http method will default to "POST"
25// _type is optional
26// id is optional
27// parentId is optional
28// version is optional
29// op_type is optional
30// routing is optional
31// timestamp is optional
32// ttl is optional
33// percolate is optional
34// timeout is optional
35// http://www.elasticsearch.org/guide/reference/api/index_.html
36func (c *Conn) Index(index string, _type string, id string, args map[string]interface{}, data interface{}) (BaseResponse, error) {
37	return c.IndexWithParameters(index, _type, id, "", 0, "", "", "", 0, "", "", false, args, data)
38}
39
40// IndexWithParameters takes all the potential parameters available
41func (c *Conn) IndexWithParameters(index string, _type string, id string, parentId string, version int, op_type string,
42	routing string, timestamp string, ttl int, percolate string, timeout string, refresh bool,
43	args map[string]interface{}, data interface{}) (BaseResponse, error) {
44	var url string
45	var retval BaseResponse
46	url, err := GetIndexUrl(index, _type, id, parentId, version, op_type, routing, timestamp, ttl, percolate, timeout, refresh)
47	if err != nil {
48		return retval, err
49	}
50	var method string
51	if len(id) == 0 {
52		method = "POST"
53	} else {
54		method = "PUT"
55	}
56	body, err := c.DoCommand(method, url, args, data)
57	if err != nil {
58		return retval, err
59	}
60	if err == nil {
61		// marshall into json
62		jsonErr := json.Unmarshal(body, &retval)
63		if jsonErr != nil {
64			return retval, jsonErr
65		}
66	}
67	return retval, err
68}
69
70func GetIndexUrl(index string, _type string, id string, parentId string, version int, op_type string,
71	routing string, timestamp string, ttl int, percolate string, timeout string, refresh bool) (retval string, e error) {
72
73	if len(index) == 0 {
74		return "", errors.New("index can not be blank")
75	}
76	var partialURL string
77	var values url.Values = url.Values{}
78	if len(_type) == 0 && len(id) > 0 {
79		e = errors.New("Can't specify id when _type is blank")
80		return
81	}
82	if len(_type) > 0 && len(id) > 0 {
83		partialURL = fmt.Sprintf("/%s/%s/%s", index, _type, id)
84	} else if len(_type) > 0 {
85		partialURL = fmt.Sprintf("/%s/%s", index, _type)
86	} else {
87		partialURL = fmt.Sprintf("/%s", index)
88	}
89	// A child document can be indexed by specifying it’s parent when indexing.
90	if len(parentId) > 0 {
91		values.Add("parent", parentId)
92	}
93	// versions start at 1, so if greater than 0
94	if version > 0 {
95		values.Add("version", strconv.Itoa(version))
96	}
97	if len(op_type) > 0 {
98		if len(id) == 0 {
99			//if id is omited, op_type defaults to 'create'
100			values.Add("op_type", "create")
101		} else {
102			values.Add("op_type", op_type)
103		}
104	}
105	if len(routing) > 0 {
106		values.Add("routing", routing)
107	}
108	// A document can be indexed with a timestamp associated with it.
109	// The timestamp value of a document can be set using the timestamp parameter.
110	if len(timestamp) > 0 {
111		values.Add("timestamp", timestamp)
112	}
113	// A document can be indexed with a ttl (time to live) associated with it. Expired documents
114	// will be expunged automatically.
115	if ttl > 0 {
116		values.Add("ttl", strconv.Itoa(ttl))
117	}
118	if len(percolate) > 0 {
119		values.Add("percolate", percolate)
120	}
121	// example 5m
122	if len(timeout) > 0 {
123		values.Add("timeout", timeout)
124	}
125
126	if refresh {
127		values.Add("refresh", "true")
128	}
129
130	partialURL += "?" + values.Encode()
131	return partialURL, nil
132}
133