Skip to content

Commit d8dfd63

Browse files
authored
GT-199 Implement Search View v2 (#434)
1 parent 41a6f37 commit d8dfd63

8 files changed

+307
-1
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- Deprecate fulltext index
1616
- Add support for Pregel API
1717
- Add tests to check support for Enterprise Graphs
18+
- Search View v2 (`search-alias`)
1819

1920
## [1.3.3](https://github.com/arangodb/go-driver/tree/v1.3.3) (2022-07-27)
2021
- Fix `lastValue` field type

database_views.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,18 @@ type DatabaseViews interface {
4141
// with given name and options, and opens a connection to it.
4242
// If a view with given name already exists within the database, a ConflictError is returned.
4343
CreateArangoSearchView(ctx context.Context, name string, options *ArangoSearchViewProperties) (ArangoSearchView, error)
44+
45+
// CreateArangoSearchAliasView creates ArangoSearch alias view with given name and options, and opens a connection to it.
46+
// If a view with given name already exists within the database, a ConflictError is returned.
47+
CreateArangoSearchAliasView(ctx context.Context, name string, options *ArangoSearchAliasViewProperties) (ArangoSearchViewAlias, error)
4448
}
4549

46-
// ViewType is the type of a view.
50+
// ViewType is the type of view.
4751
type ViewType string
4852

4953
const (
5054
// ViewTypeArangoSearch specifies an ArangoSearch view type.
5155
ViewTypeArangoSearch = ViewType("arangosearch")
56+
// ViewTypeArangoSearchAlias specifies an ArangoSearch view type alias.
57+
ViewTypeArangoSearchAlias = ViewType("search-alias")
5258
)

database_views_impl.go

+42
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,45 @@ func (d *database) CreateArangoSearchView(ctx context.Context, name string, opti
158158

159159
return result, nil
160160
}
161+
162+
// CreateArangoSearchAliasView creates a new view of type search-alias,
163+
// with given name and options, and opens a connection to it.
164+
// If a view with given name already exists within the database, a ConflictError is returned.
165+
func (d *database) CreateArangoSearchAliasView(ctx context.Context, name string, options *ArangoSearchAliasViewProperties) (ArangoSearchViewAlias, error) {
166+
input := struct {
167+
Name string `json:"name"`
168+
Type ViewType `json:"type"`
169+
ArangoSearchAliasViewProperties
170+
}{
171+
Name: name,
172+
Type: ViewTypeArangoSearchAlias,
173+
}
174+
if options != nil {
175+
input.ArangoSearchAliasViewProperties = *options
176+
}
177+
req, err := d.conn.NewRequest("POST", path.Join(d.relPath(), "_api/view"))
178+
if err != nil {
179+
return nil, WithStack(err)
180+
}
181+
if _, err := req.SetBody(input); err != nil {
182+
return nil, WithStack(err)
183+
}
184+
applyContextSettings(ctx, req)
185+
resp, err := d.conn.Do(ctx, req)
186+
if err != nil {
187+
return nil, WithStack(err)
188+
}
189+
if err := resp.CheckStatus(201); err != nil {
190+
return nil, WithStack(err)
191+
}
192+
view, err := newView(name, input.Type, d)
193+
if err != nil {
194+
return nil, WithStack(err)
195+
}
196+
result, err := view.ArangoSearchViewAlias()
197+
if err != nil {
198+
return nil, WithStack(err)
199+
}
200+
201+
return result, nil
202+
}

test/view_alias_test.go

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/arangodb/go-driver"
8+
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
// ensureArangoSearchView is a helper to check if an arangosearch view exists and create it if needed.
13+
// It will fail the test when an error occurs.
14+
func ensureArangoSearchAliasView(ctx context.Context, db driver.Database, name string, options *driver.ArangoSearchAliasViewProperties, t testEnv) driver.ArangoSearchViewAlias {
15+
v, err := db.View(ctx, name)
16+
if driver.IsNotFound(err) {
17+
v, err = db.CreateArangoSearchAliasView(ctx, name, options)
18+
if err != nil {
19+
t.Fatalf("Failed to create arangosearch view '%s': %s", name, describe(err))
20+
}
21+
} else if err != nil {
22+
t.Fatalf("Failed to open view '%s': %s", name, describe(err))
23+
}
24+
result, err := v.ArangoSearchViewAlias()
25+
if err != nil {
26+
t.Fatalf("Failed to open view '%s' as arangosearch view: %s", name, describe(err))
27+
}
28+
return result
29+
}
30+
31+
// TestSearchViewsAlias tests the arangosearch view alias methods
32+
func TestSearchViewsAlias(t *testing.T) {
33+
ctx := context.Background()
34+
c := createClientFromEnv(t, true)
35+
skipBelowVersion(c, "3.10", t)
36+
skipBelowVersion(c, "3.10", t)
37+
db := ensureDatabase(ctx, c, "search_view_test_basic", nil, t)
38+
39+
nameAlias := "test_add_collection_view_alias"
40+
nameCol := "col_in_alias_view"
41+
nameInvInd := "inv_index_alias_view"
42+
43+
col := ensureCollection(ctx, db, nameCol, nil, t)
44+
v := ensureArangoSearchAliasView(ctx, db, nameAlias, nil, t)
45+
46+
p, err := v.Properties(ctx)
47+
require.NoError(t, err)
48+
require.Equal(t, p.Type, driver.ViewTypeArangoSearchAlias)
49+
require.Equal(t, p.Name, nameAlias)
50+
require.Len(t, p.Indexes, 0)
51+
52+
_, err = v.ArangoSearchView()
53+
require.Error(t, err)
54+
55+
indexOpt := driver.InvertedIndexOptions{
56+
Name: nameInvInd,
57+
PrimarySort: driver.InvertedIndexPrimarySort{
58+
Fields: []driver.ArangoSearchPrimarySortEntry{
59+
{Field: "test1", Ascending: newBool(true)},
60+
{Field: "test2", Ascending: newBool(false)},
61+
},
62+
Compression: driver.PrimarySortCompressionLz4,
63+
},
64+
Fields: []driver.InvertedIndexField{
65+
{Name: "field1", Features: []driver.ArangoSearchAnalyzerFeature{driver.ArangoSearchAnalyzerFeatureFrequency}, Nested: nil},
66+
{Name: "field2", Features: []driver.ArangoSearchAnalyzerFeature{driver.ArangoSearchAnalyzerFeaturePosition}, TrackListPositions: false, Nested: nil},
67+
},
68+
}
69+
idx, created, err := col.EnsureInvertedIndex(ctx, &indexOpt)
70+
require.NoError(t, err)
71+
require.True(t, created)
72+
require.Equal(t, nameInvInd, idx.UserName())
73+
74+
opt := driver.ArangoSearchAliasViewProperties{
75+
Indexes: []driver.ArangoSearchAliasIndex{
76+
{
77+
Collection: nameCol,
78+
Index: nameInvInd,
79+
},
80+
},
81+
}
82+
p, err = v.SetProperties(ctx, opt)
83+
require.NoError(t, err)
84+
require.Equal(t, p.Type, driver.ViewTypeArangoSearchAlias)
85+
require.Equal(t, p.Name, nameAlias)
86+
require.Len(t, p.Indexes, 1)
87+
require.Equal(t, p.Indexes[0].Collection, nameCol)
88+
require.Equal(t, p.Indexes[0].Index, nameInvInd)
89+
90+
p, err = v.Properties(ctx)
91+
require.NoError(t, err)
92+
require.Equal(t, p.Type, driver.ViewTypeArangoSearchAlias)
93+
require.Equal(t, p.Name, nameAlias)
94+
require.Len(t, p.Indexes, 1)
95+
96+
views, err := db.Views(ctx)
97+
require.NoError(t, err)
98+
require.Len(t, views, 1)
99+
100+
exist, err := db.ViewExists(ctx, nameAlias)
101+
require.NoError(t, err)
102+
require.True(t, exist)
103+
104+
vv, err := db.View(ctx, nameAlias)
105+
require.NoError(t, err)
106+
require.Equal(t, vv.Name(), nameAlias)
107+
108+
err = v.Remove(ctx)
109+
require.NoError(t, err)
110+
111+
views, err = db.Views(ctx)
112+
require.NoError(t, err)
113+
require.Len(t, views, 0)
114+
}

view.go

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ type View interface {
3939
// When the type of the view is not ArangoSearch, an error is returned.
4040
ArangoSearchView() (ArangoSearchView, error)
4141

42+
// ArangoSearchViewAlias returns this view as an ArangoSearch view alias.
43+
// When the type of the view is not ArangoSearch alias, an error is returned.
44+
ArangoSearchViewAlias() (ArangoSearchViewAlias, error)
45+
4246
// Database returns the database containing the view.
4347
Database() Database
4448

view_arangosearch_alias.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Ewout Prangsma
21+
//
22+
23+
package driver
24+
25+
import (
26+
"context"
27+
)
28+
29+
// ArangoSearchViewAlias provides access to the information of a view alias
30+
// Views aliases are only available in ArangoDB 3.10 and higher.
31+
type ArangoSearchViewAlias interface {
32+
// View Include generic View functions
33+
View
34+
35+
// Properties fetches extended information about the view.
36+
Properties(ctx context.Context) (ArangoSearchAliasViewProperties, error)
37+
38+
// SetProperties changes properties of the view.
39+
SetProperties(ctx context.Context, options ArangoSearchAliasViewProperties) (ArangoSearchAliasViewProperties, error)
40+
}
41+
42+
type ArangoSearchAliasViewProperties struct {
43+
ArangoSearchViewBase
44+
45+
// Indexes A list of inverted indexes to add to the View.
46+
Indexes []ArangoSearchAliasIndex `json:"indexes,omitempty"`
47+
}
48+
49+
type ArangoSearchAliasIndex struct {
50+
// Collection The name of a collection.
51+
Collection string `json:"collection"`
52+
// Index The name of an inverted index of the collection.
53+
Index string `json:"index"`
54+
}

view_arangosearch_alias_impl.go

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Ewout Prangsma
21+
//
22+
23+
package driver
24+
25+
import (
26+
"context"
27+
"path"
28+
)
29+
30+
// viewArangoSearchAlias implements ArangoSearchViewAlias
31+
type viewArangoSearchAlias struct {
32+
view
33+
}
34+
35+
// Properties fetches extended information about the view.
36+
func (v *viewArangoSearchAlias) Properties(ctx context.Context) (ArangoSearchAliasViewProperties, error) {
37+
req, err := v.conn.NewRequest("GET", path.Join(v.relPath(), "properties"))
38+
if err != nil {
39+
return ArangoSearchAliasViewProperties{}, WithStack(err)
40+
}
41+
applyContextSettings(ctx, req)
42+
resp, err := v.conn.Do(ctx, req)
43+
if err != nil {
44+
return ArangoSearchAliasViewProperties{}, WithStack(err)
45+
}
46+
if err := resp.CheckStatus(200); err != nil {
47+
return ArangoSearchAliasViewProperties{}, WithStack(err)
48+
}
49+
var data ArangoSearchAliasViewProperties
50+
if err := resp.ParseBody("", &data); err != nil {
51+
return ArangoSearchAliasViewProperties{}, WithStack(err)
52+
}
53+
return data, nil
54+
}
55+
56+
// SetProperties changes properties of the view.
57+
func (v *viewArangoSearchAlias) SetProperties(ctx context.Context, options ArangoSearchAliasViewProperties) (ArangoSearchAliasViewProperties, error) {
58+
req, err := v.conn.NewRequest("PUT", path.Join(v.relPath(), "properties"))
59+
if err != nil {
60+
return ArangoSearchAliasViewProperties{}, WithStack(err)
61+
}
62+
if _, err := req.SetBody(options); err != nil {
63+
return ArangoSearchAliasViewProperties{}, WithStack(err)
64+
}
65+
applyContextSettings(ctx, req)
66+
resp, err := v.conn.Do(ctx, req)
67+
if err != nil {
68+
return ArangoSearchAliasViewProperties{}, WithStack(err)
69+
}
70+
if err := resp.CheckStatus(200); err != nil {
71+
return ArangoSearchAliasViewProperties{}, WithStack(err)
72+
}
73+
var data ArangoSearchAliasViewProperties
74+
if err := resp.ParseBody("", &data); err != nil {
75+
return ArangoSearchAliasViewProperties{}, WithStack(err)
76+
}
77+
return data, nil
78+
}

view_impl.go

+7
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ func (v *view) ArangoSearchView() (ArangoSearchView, error) {
8080
return &viewArangoSearch{view: *v}, nil
8181
}
8282

83+
func (v *view) ArangoSearchViewAlias() (ArangoSearchViewAlias, error) {
84+
if v.viewType != ViewTypeArangoSearchAlias {
85+
return nil, WithStack(newArangoError(http.StatusConflict, 0, fmt.Sprintf("Type must be '%s', got '%s'", ViewTypeArangoSearchAlias, v.viewType)))
86+
}
87+
return &viewArangoSearchAlias{view: *v}, nil
88+
}
89+
8390
// Database returns the database containing the view.
8491
func (v *view) Database() Database {
8592
return v.db

0 commit comments

Comments
 (0)