diff --git a/arangodb-net-standard.Test/ViewApi/ViewApiClientTest.cs b/arangodb-net-standard.Test/ViewApi/ViewApiClientTest.cs new file mode 100644 index 00000000..31c74df3 --- /dev/null +++ b/arangodb-net-standard.Test/ViewApi/ViewApiClientTest.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using ArangoDBNetStandard; +using ArangoDBNetStandard.ViewApi; +using ArangoDBNetStandard.ViewApi.Models; +using ArangoDBNetStandard.Transport; +using Moq; +using Xunit; + +namespace ArangoDBNetStandardTest.ViewApi +{ + public class ViewApiClientTest : IClassFixture, IAsyncLifetime + { + private ViewApiClient _viewApi; + private ArangoDBClient _adb; + + public ViewApiClientTest(ViewApiClientTestFixture fixture) + { + _adb = fixture.ArangoDBClient; + _viewApi = _adb.View; + } + + public Task InitializeAsync() + { + return Task.CompletedTask; + } + + public Task DisposeAsync() + { + return Task.CompletedTask; + } + + [Fact] + public async Task GetAllViewsAsync_ShouldSucceed() + { + var testName = "GetAllViewsAsyncShouldSucceedView"; + var createResponse = await _viewApi.PostCreateViewAsync( + new ViewDetails() + { + Name = testName, + Type = "arangosearch" + }); + var res = await _viewApi.GetAllViewsAsync(); + + Assert.Equal(HttpStatusCode.OK, res.Code); + Assert.False(res.Error); + Assert.NotNull(res.Result); + Assert.NotEmpty(res.Result); + } + + [Fact] + public async Task PostCreateViewAsync_ShouldSucceed() + { + var testName = "PostCreateViewAsyncShouldSucceedView"; + var res = await _viewApi.PostCreateViewAsync( + new ViewDetails() + { + Name = testName, + Type = "arangosearch" + }); + Assert.NotNull(res); + Assert.NotNull(res.GloballyUniqueId); + } + + [Fact] + public async Task DeleteViewAsync_ShouldSucceed() + { + var testName = "DeleteViewAsyncShouldSucceedView"; + var createResponse = await _viewApi.PostCreateViewAsync( + new ViewDetails() + { + Name = testName, + Type = "arangosearch" + }); + var res = await _viewApi.DeleteViewAsync(testName); + + Assert.Equal(HttpStatusCode.OK, res.Code); + Assert.False(res.Error); + Assert.True(res.Result); + } + + [Fact] + public async Task GetViewAsync_ShouldSucceed() + { + var testName = "GetViewAsyncShouldSucceedView"; + var createResponse = await _viewApi.PostCreateViewAsync( + new ViewDetails() + { + Name = testName, + Type = "arangosearch" + }); + var res = await _viewApi.GetViewAsync(testName); + + Assert.Equal(HttpStatusCode.OK, res.Code); + Assert.False(res.Error); + } + + [Fact] + public async Task GetViewPropertiesAsync_ShouldSucceed() + { + var testName = "GetViewPropertiesAsyncShouldSucceedView"; + var createResponse = await _viewApi.PostCreateViewAsync( + new ViewDetails() + { + Name = testName, + Type = "arangosearch" + }); + var res = await _viewApi.GetViewPropertiesAsync(testName); + + Assert.Equal(HttpStatusCode.OK, res.Code); + Assert.False(res.Error); + Assert.NotNull(res.GloballyUniqueId); + } + + [Fact] + public async Task PutRenameViewAsync_ShouldSucceed() + { + var testName = "PutRenameViewAsyncShouldSucceedView"; + var newName = "PutRenameViewAsyncShouldSucceedViewRenamed"; + var createResponse = await _viewApi.PostCreateViewAsync( + new ViewDetails() + { + Name = testName, + Type = "arangosearch" + }); + var res = await _viewApi.PutRenameViewAsync( + testName, + new PutRenameViewBody() + { + Name = newName + }); + + Assert.Equal(HttpStatusCode.OK, res.Code); + Assert.False(res.Error); + Assert.NotNull(res.GloballyUniqueId); + Assert.Equal(newName, res.Name); + } + } +} \ No newline at end of file diff --git a/arangodb-net-standard.Test/ViewApi/ViewApiClientTestFixture.cs b/arangodb-net-standard.Test/ViewApi/ViewApiClientTestFixture.cs new file mode 100644 index 00000000..2ac3f106 --- /dev/null +++ b/arangodb-net-standard.Test/ViewApi/ViewApiClientTestFixture.cs @@ -0,0 +1,46 @@ +using ArangoDBNetStandard; +using ArangoDBNetStandard.CollectionApi.Models; +using ArangoDBNetStandard.ViewApi.Models; +using System; +using System.Threading.Tasks; + +namespace ArangoDBNetStandardTest.ViewApi +{ + public class ViewApiClientTestFixture : ApiClientTestFixtureBase + { + public ArangoDBClient ArangoDBClient { get; internal set; } + + public ViewApiClientTestFixture() + { + } + + public override async Task InitializeAsync() + { + await base.InitializeAsync(); + + Console.WriteLine("ViewApiClientTestFixture.InitializeAsync() started."); + + string dbName = nameof(ViewApiClientTestFixture); + await CreateDatabase(dbName); + Console.WriteLine("Database " + dbName + " created successfully"); + + ArangoDBClient = GetArangoDBClient(dbName); + try + { + var dbRes = await ArangoDBClient.Database.GetCurrentDatabaseInfoAsync(); + if (dbRes.Error) + throw new Exception("GetCurrentDatabaseInfoAsync failed: " + dbRes.Code.ToString()); + else + { + Console.WriteLine("In database " + dbRes.Result.Name); + } + } + catch (ApiErrorException ex) + { + Console.WriteLine(ex.Message); + throw ex; + } + + } + } +} diff --git a/arangodb-net-standard/ArangoDBClient.cs b/arangodb-net-standard/ArangoDBClient.cs index e166d46e..f5b37341 100644 --- a/arangodb-net-standard/ArangoDBClient.cs +++ b/arangodb-net-standard/ArangoDBClient.cs @@ -13,6 +13,7 @@ using ArangoDBNetStandard.Transport; using ArangoDBNetStandard.Transport.Http; using ArangoDBNetStandard.UserApi; +using ArangoDBNetStandard.ViewApi; namespace ArangoDBNetStandard { @@ -77,7 +78,12 @@ public class ArangoDBClient : IArangoDBClient public IndexApiClient Index { get; private set; } /// - /// Index management API. + /// View management API. + /// + public ViewApiClient View { get; private set; } + + /// + /// Analyzer management API. /// public AnalyzerApiClient Analyzer { get; private set; } @@ -144,6 +150,7 @@ private void InitializeApis( Graph = new GraphApiClient(transport, serialization); User = new UserApiClient(transport, serialization); Index = new IndexApiClient(transport, serialization); + View = new ViewApiClient(transport, serialization); Analyzer = new AnalyzerApiClient(transport, serialization); } } diff --git a/arangodb-net-standard/IArangoDBClient.cs b/arangodb-net-standard/IArangoDBClient.cs index 8e0134ca..8f58c74b 100644 --- a/arangodb-net-standard/IArangoDBClient.cs +++ b/arangodb-net-standard/IArangoDBClient.cs @@ -10,6 +10,7 @@ using ArangoDBNetStandard.IndexApi; using ArangoDBNetStandard.TransactionApi; using ArangoDBNetStandard.UserApi; +using ArangoDBNetStandard.ViewApi; namespace ArangoDBNetStandard { @@ -66,8 +67,13 @@ public interface IArangoDBClient : IDisposable IndexApiClient Index { get; } /// + /// View management API. + /// + ViewApiClient View { get; } + + /// /// Analyzer API. /// AnalyzerApiClient Analyzer { get; } } -} +} \ No newline at end of file diff --git a/arangodb-net-standard/ViewApi/IViewsApiClient.cs b/arangodb-net-standard/ViewApi/IViewsApiClient.cs new file mode 100644 index 00000000..70214952 --- /dev/null +++ b/arangodb-net-standard/ViewApi/IViewsApiClient.cs @@ -0,0 +1,79 @@ +using ArangoDBNetStandard.ViewApi.Models; +using System.Threading.Tasks; + +namespace ArangoDBNetStandard.ViewApi +{ + /// + /// Defines a client to access the ArangoDB API for Views. + /// + public interface IViewApiClient + { + /// + /// Gets a list of all views in a database, + /// regardless of their type. + /// GET /_api/view + /// + /// + Task GetAllViewsAsync(); + + /// + /// Create a new View + /// POST /_api/view + /// + /// The body of the request containing required properties. + /// + Task PostCreateViewAsync(ViewDetails body); + + /// + /// Delete / drop a view + /// DELETE /_api/view/{view-name} + /// + /// The name or identifier of the view to drop. + /// + Task DeleteViewAsync(string viewNameOrId); + + /// + /// Get information about a view + /// GET /_api/view/{view-name} + /// + /// The name or identifier of the view to drop. + /// + Task GetViewAsync(string viewNameOrId); + + /// + /// Get the properties of a view + /// GET /_api/view/{view-name}/properties + /// + /// The name or identifier of the view to drop. + /// + Task GetViewPropertiesAsync(string viewNameOrId); + + /// + /// Partially changes properties of a view + /// PATCH /_api/view/{view-name}/properties + /// + /// The name or identifier of the view. + /// The body of the request containing required properties. + /// + Task PatchViewPropertiesAsync(string viewNameOrId, ViewDetails body); + + /// + /// Changes all properties of a view + /// PUT /_api/view/{view-name}/properties + /// + /// The name of the view. + /// The body of the request containing required properties. + /// + Task PutViewPropertiesAsync(string viewName, ViewDetails body); + + /// + /// Renames a view + /// PUT /_api/view/{view-name}/rename + /// + /// The name of the view. + /// The body of the request containing required properties. + /// + /// Note: This method is not available in a cluster. + Task PutRenameViewAsync(string viewName, PutRenameViewBody body); + } +} \ No newline at end of file diff --git a/arangodb-net-standard/ViewApi/Models/DeleteViewResponse.cs b/arangodb-net-standard/ViewApi/Models/DeleteViewResponse.cs new file mode 100644 index 00000000..1885820a --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/DeleteViewResponse.cs @@ -0,0 +1,14 @@ +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Response from + /// + public class DeleteViewResponse :ResponseBase + { + /// + /// Indicates whether the delete + /// operation was successful. + /// + public bool Result { get; set; } + } +} diff --git a/arangodb-net-standard/ViewApi/Models/GetAllViewsResponse.cs b/arangodb-net-standard/ViewApi/Models/GetAllViewsResponse.cs new file mode 100644 index 00000000..0edf8cda --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/GetAllViewsResponse.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Response from + /// + public class GetAllViewsResponse : ResponseBase + { + /// + /// List of views + /// + public List Result { get; set; } + } +} diff --git a/arangodb-net-standard/ViewApi/Models/GetViewPropertiesResponse.cs b/arangodb-net-standard/ViewApi/Models/GetViewPropertiesResponse.cs new file mode 100644 index 00000000..3917c90c --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/GetViewPropertiesResponse.cs @@ -0,0 +1,20 @@ +using System.Net; + +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Response from + /// + public class GetViewPropertiesResponse : ViewResponse + { + /// + /// Indicates whether an error occurred + /// + public bool Error { get; set; } + + /// + /// The HTTP status code. + /// + public HttpStatusCode Code { get; set; } + } +} diff --git a/arangodb-net-standard/ViewApi/Models/GetViewResponse.cs b/arangodb-net-standard/ViewApi/Models/GetViewResponse.cs new file mode 100644 index 00000000..f6daad2d --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/GetViewResponse.cs @@ -0,0 +1,20 @@ +using System.Net; + +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Response from + /// + public class GetViewResponse : ViewSummary + { + /// + /// Indicates whether an error occurred + /// + public bool Error { get; set; } + + /// + /// The HTTP status code. + /// + public HttpStatusCode Code { get; set; } + } +} \ No newline at end of file diff --git a/arangodb-net-standard/ViewApi/Models/LinkProperties.cs b/arangodb-net-standard/ViewApi/Models/LinkProperties.cs new file mode 100644 index 00000000..fb3cd8d5 --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/LinkProperties.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; + +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Properties for linked attribute value + /// + /// + public class LinkProperties + { + /// + /// Possible value for + /// Store information about value presence to + /// allow use of the EXISTS() function. + /// + public const string NoStoreValue = "none"; + + /// + /// Possible value for + /// Do not store value meta data in the View. + /// + public const string IdStoreValue = "id"; + + /// + /// A list of analyzers, by name as defined + /// via the Analyzers feature, that should + /// be applied to values of processed + /// document attributes. + /// + public List Analyzers { get; set; } + + /// + /// Fields that should be processed at each + /// level of the document. Each key specifies + /// the document attribute/field to be processed. + /// Note that the value of includeAllFields is + /// also consulted when selecting fields to be + /// processed. Each value specifies the Link + /// properties directives to be used when processing + /// the specified field, an empty/null value denotes + /// inheritance of all (except fields) directives + /// from the current level. + /// + public IDictionary Fields { get; set; } + + /// + /// If set to true, then process all document attributes. + /// Otherwise, only consider attributes mentioned in fields. + /// Attributes not explicitly specified in fields will be + /// processed with default link properties, i.e. null. + /// Using includeAllFields for a lot of attributes in + /// combination with complex Analyzers may significantly + /// slow down the indexing process. + /// + public bool IncludeAllFields { get; set; } + + /// + /// If set to true, then for array values track the value + /// position in arrays. E.g., when querying for the input + /// { attr: [ "valueX", "valueY", "valueZ" ] }, the user + /// must specify: doc.attr[1] == "valueY". Otherwise, all + /// values in an array are treated as equal alternatives. + /// E.g., when querying for the input + /// { attr: [ "valueX", "valueY", "valueZ" ] }, the user + /// must specify: doc.attr == "valueY" + /// + public bool TrackListPositions { get; set; } + + /// + /// Controls how the view should keep track of the + /// attribute values. Valid values are + /// and . + /// Not to be confused with , + /// which stores attribute values in the View index. + /// + public string StoreValues { get; set; } + + /// + /// If set to true, then no exclusive lock is used on the + /// source collection during View index creation, so that + /// it remains basically available. This option can be set + /// when adding links. It does not get persisted as it is + /// not a View property, but only a one-off option. + /// + public bool InBackground { get; set; } + } +} \ No newline at end of file diff --git a/arangodb-net-standard/ViewApi/Models/PutRenameViewBody.cs b/arangodb-net-standard/ViewApi/Models/PutRenameViewBody.cs new file mode 100644 index 00000000..18e0e2d7 --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/PutRenameViewBody.cs @@ -0,0 +1,14 @@ +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Body parameters for + /// + public class PutRenameViewBody + { + /// + /// The new name for the view + /// + public string Name { get; set; } + } + +} diff --git a/arangodb-net-standard/ViewApi/Models/PutRenameViewResponse.cs b/arangodb-net-standard/ViewApi/Models/PutRenameViewResponse.cs new file mode 100644 index 00000000..97b2ee27 --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/PutRenameViewResponse.cs @@ -0,0 +1,20 @@ +using System.Net; + +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Response from + /// + public class PutRenameViewResponse : ViewSummary + { + /// + /// Indicates whether an error occurred + /// + public bool Error { get; set; } + + /// + /// The HTTP status code. + /// + public HttpStatusCode Code { get; set; } + } +} diff --git a/arangodb-net-standard/ViewApi/Models/ResponseBase.cs b/arangodb-net-standard/ViewApi/Models/ResponseBase.cs new file mode 100644 index 00000000..c1578c7a --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/ResponseBase.cs @@ -0,0 +1,21 @@ +using System.Net; + +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Represents a common response class for Views API operations. + /// + public class ResponseBase + { + /// + /// Indicates whether an error occurred + /// + public bool Error { get; set; } + + /// + /// The HTTP status code. + /// + public HttpStatusCode Code { get; set; } + } + +} diff --git a/arangodb-net-standard/ViewApi/Models/ViewConsolidationPolicy.cs b/arangodb-net-standard/ViewApi/Models/ViewConsolidationPolicy.cs new file mode 100644 index 00000000..f51dbc07 --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/ViewConsolidationPolicy.cs @@ -0,0 +1,76 @@ +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// The consolidation policy to apply + /// for selecting which segments should be merged. + /// Read more about this in the documentation. + /// + public class ViewConsolidationPolicy + { + /// + /// Possible value for + /// + public const string TierType = "tier"; + /// + /// Possible value for + /// + public const string BytesAccumulationType = "bytes_accum"; + + /// + /// The type of consolidation policy. + /// 1) (default): consolidate + /// based on segment byte size and live + /// document count as dictated by the + /// customization attributes. + /// If this type is used, then below + /// , + /// , + /// , + /// and + /// are specified. + /// 2) : consolidate only + /// if the sum of all candidate segment + /// byte size is less than the total + /// segment byte size multiplied by + /// the . + /// + public string Type { get; set; } + + /// + /// Value in the range [0.0, 1.0] + /// + public decimal? Threshold { get; set; } + + /// + /// The value (in bytes) to treat all + /// smaller segments as equal for + /// consolidation selection (default: 2097152) + /// + public long? SegmentsBytesFloor { get; set; } + + /// + /// Maximum allowed size of all consolidated + /// segments in bytes (default: 5368709120) + /// + public long? SegmentsBytesMax { get; set; } + + /// + /// The maximum number of segments that + /// will be evaluated as candidates + /// for consolidation (default: 10) + /// + public long? SegmentsMax { get; set; } + + /// + /// The minimum number of segments that + /// will be evaluated as candidates + /// for consolidation (default: 1) + /// + public long? SegmentsMin { get; set; } + + /// + /// Specified if is . + /// + public long? MinScore { get; set; } + } +} \ No newline at end of file diff --git a/arangodb-net-standard/ViewApi/Models/ViewDetails.cs b/arangodb-net-standard/ViewApi/Models/ViewDetails.cs new file mode 100644 index 00000000..915d3d2f --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/ViewDetails.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; + +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Detailed properties of a view + /// + public class ViewDetails + { + /// + /// Possible value for + /// + public const string ArangoSearchViewType = "arangosearch"; + + /// + /// Possible value for + /// + public const string LZ4SortCompression = "lz4"; + + /// + /// Possible value for + /// + public const string NoSortCompression = "none"; + + /// + /// The name of the View. + /// + public string Name { get; set; } + + /// + /// The type of the View. + /// Must be set to + /// when creating a view. + /// This option is immutable. + /// + public string Type { get; set; } + + /// + /// The number of commits between + /// removing unused files in + /// the ArangoSearch data directory + /// (default: 2, to disable use: 0). + /// Read more about this in the documentation. + /// + public int CleanupIntervalStep { get; set; } + + /// + /// The number of milliseconds to wait + /// between committing View data store + /// changes and making documents visible + /// to queries (default: 1000, to disable use: 0) + /// Read more about this in the documentation. + /// + public int CommitIntervalMsec { get; set; } + + /// + /// The number of milliseconds to wait + /// between applying ‘consolidationPolicy’ + /// to consolidate View data store and + /// possibly release space on the filesystem + /// (default: 10000, to disable use: 0). + /// Read more about this in the documentation. + /// + public int ConsolidationIntervalMsec { get; set; } + + /// + /// The consolidation policy to apply + /// for selecting which segments should be merged. + /// Read more about this in the documentation. + /// + public ViewConsolidationPolicy ConsolidationPolicy { get; set; } + + /// + /// A primary sort order can be defined + /// to enable an AQL optimization. + /// Read more about this in the documentation. + /// + public List PrimarySort { get; set; } + + /// + /// Defines how to compress the primary sort data + /// (introduced in v3.7.1). ArangoDB v3.5 and v3.6 + /// always compress the index using LZ4. + /// This option is immutable. Possible values: + /// 1) (default): use LZ4 fast compression. + /// 2) : disable compression to trade space for speed. + /// Read more about this in the documentation. + /// + public string PrimarySortCompression { get; set; } + + /// + /// An array of objects to describe which document + /// attributes to store in the View index (introduced in v3.7.1). + /// It can then cover search queries, which means + /// the data can be taken from the index directly + /// and accessing the storage engine can be avoided. + /// + public List StoredValues { get; set; } + + /// + /// Maximum number of concurrent active + /// writers (segments) that perform a transaction. + /// Other writers (segments) wait till current + /// active writers (segments) finish + /// (default: 0, use 0 to disable, immutable) + /// + public int? WritebufferActive { get; set; } + + /// + /// Maximum number of writers (segments) + /// cached in the pool + /// (default: 64, use 0 to disable, immutable) + /// + public int? WritebufferIdle { get; set; } + + /// + /// Maximum memory byte size per writer + /// (segment) before a writer (segment) + /// flush is triggered. + /// + public int? WritebufferSizeMax { get; set; } + + /// + /// Expects an object with the attribute keys + /// being names of to be linked collections, + /// and the link properties as attribute values. + /// + public IDictionary Links { get; set; } + } +} \ No newline at end of file diff --git a/arangodb-net-standard/ViewApi/Models/ViewResponse.cs b/arangodb-net-standard/ViewApi/Models/ViewResponse.cs new file mode 100644 index 00000000..d2cb9efe --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/ViewResponse.cs @@ -0,0 +1,18 @@ +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Response from several View API endpoints + /// + public class ViewResponse : ViewDetails + { + /// + /// The globally unique identifier of the View + /// + public string GloballyUniqueId { get; set; } + + /// + /// The id of the view + /// + public string Id { get; set; } + } +} diff --git a/arangodb-net-standard/ViewApi/Models/ViewSort.cs b/arangodb-net-standard/ViewApi/Models/ViewSort.cs new file mode 100644 index 00000000..5153e3c6 --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/ViewSort.cs @@ -0,0 +1,32 @@ +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Defines sort order for a view. + /// Read more about this in the documentation. + /// + public class ViewSort + { + /// + /// Possible value for + /// + public const string AscendingSortDirection = "asc"; + + /// + /// Possible value for + /// + public const string DescendingSortDirection = "desc"; + + /// + /// Name of the field to sort by + /// + public string Field { get; set; } + + /// + /// Direction of the sort: + /// ( for ascending, + /// for descending) + /// + public string Direction { get; set; } + } + +} diff --git a/arangodb-net-standard/ViewApi/Models/ViewStoredValue.cs b/arangodb-net-standard/ViewApi/Models/ViewStoredValue.cs new file mode 100644 index 00000000..9599ee43 --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/ViewStoredValue.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Describes which document attributes + /// to store in a View index. + /// + public class ViewStoredValue + { + /// + /// Possible value for + /// + public const string NoCompression = "none"; + + /// + /// Possible value for + /// + public const string LZ4Compression = "lz4"; + + /// + /// One or more document attribute paths. + /// The specified attributes are placed + /// into a single column of the index. + /// A column with all fields that are + /// involved in common search queries + /// is ideal for performance. The column + /// should not include too many unneeded + /// fields. + /// + public List Fields { get; set; } + + /// + /// Optional when creating views. Defines + /// the compression type used for the + /// internal column-store, which can be + /// (LZ4 fast compression, default) + /// OR (no compression). + /// + public string Compression { get; set; } + } +} \ No newline at end of file diff --git a/arangodb-net-standard/ViewApi/Models/ViewSummary.cs b/arangodb-net-standard/ViewApi/Models/ViewSummary.cs new file mode 100644 index 00000000..2dd167b5 --- /dev/null +++ b/arangodb-net-standard/ViewApi/Models/ViewSummary.cs @@ -0,0 +1,28 @@ +namespace ArangoDBNetStandard.ViewApi.Models +{ + /// + /// Provides summary info about a view + /// + public class ViewSummary + { + /// + /// The globally unique identifier of the View + /// + public string GloballyUniqueId { get; set; } + + /// + /// The identifier of the View + /// + public string Id { get; set; } + + /// + /// The name of the View + /// + public string Name { get; set; } + + /// + /// The type of the View + /// + public string Type { get; set; } + } +} \ No newline at end of file diff --git a/arangodb-net-standard/ViewApi/ViewsApiClient.cs b/arangodb-net-standard/ViewApi/ViewsApiClient.cs new file mode 100644 index 00000000..689a91eb --- /dev/null +++ b/arangodb-net-standard/ViewApi/ViewsApiClient.cs @@ -0,0 +1,215 @@ +using ArangoDBNetStandard.ViewApi.Models; +using ArangoDBNetStandard.Serialization; +using ArangoDBNetStandard.Transport; +using System.Net; +using System.Threading.Tasks; + +namespace ArangoDBNetStandard.ViewApi +{ + /// + /// A client to interact with ArangoDB HTTP API endpoints + /// for views management. + /// + public class ViewApiClient : ApiClientBase, IViewApiClient + { + /// + /// The transport client used to communicate with the ArangoDB host. + /// + protected readonly IApiClientTransport _transport; + + /// + /// The root path of the API. + /// + protected readonly string _apiPath = "_api/view"; + + /// + /// Create an instance of + /// using the provided transport layer and the default JSON serialization. + /// + /// + public ViewApiClient(IApiClientTransport transport) + : base(new JsonNetApiClientSerialization()) + { + _transport = transport; + } + + /// + /// Create an instance of + /// using the provided transport and serialization layers. + /// + /// + /// + public ViewApiClient(IApiClientTransport transport, IApiClientSerialization serializer) + : base(serializer) + { + _transport = transport; + } + + /// + /// Gets a list of all views in a database, + /// regardless of their type. + /// GET /_api/view + /// + /// + public virtual async Task GetAllViewsAsync() + { + string uri = _apiPath; + using (var response = await _transport.GetAsync(uri).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return DeserializeJsonFromStream(stream); + } + throw await GetApiErrorException(response).ConfigureAwait(false); + } + } + + /// + /// Create a new View + /// POST /_api/view + /// + /// The body of the request containing required properties. + /// + public virtual async Task PostCreateViewAsync(ViewDetails body) + { + string uri = _apiPath; + var content = GetContent(body, new ApiClientSerializationOptions(true, true)); + using (var response = await _transport.PostAsync(uri, content).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return DeserializeJsonFromStream(stream); + } + throw await GetApiErrorException(response).ConfigureAwait(false); + } + } + + /// + /// Delete / drop a view + /// DELETE /_api/view/{view-name} + /// + /// The name or identifier of the view to drop. + /// + public virtual async Task DeleteViewAsync(string viewNameOrId) + { + string uri = _apiPath + '/' + viewNameOrId; + using (var response = await _transport.DeleteAsync(uri).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return DeserializeJsonFromStream(stream); + } + throw await GetApiErrorException(response).ConfigureAwait(false); + } + } + + /// + /// Get information about a view + /// GET /_api/view/{view-name} + /// + /// The name or identifier of the view to drop. + /// + public virtual async Task GetViewAsync(string viewNameOrId) + { + string uri = _apiPath + '/' + viewNameOrId; + using (var response = await _transport.GetAsync(uri).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return DeserializeJsonFromStream(stream); + } + throw await GetApiErrorException(response).ConfigureAwait(false); + } + } + + /// + /// Get the properties of a view + /// GET /_api/view/{view-name}/properties + /// + /// The name or identifier of the view to drop. + /// + public virtual async Task GetViewPropertiesAsync(string viewNameOrId) + { + string uri = $"{_apiPath}/{viewNameOrId}/properties"; + using (var response = await _transport.GetAsync(uri).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return DeserializeJsonFromStream(stream); + } + throw await GetApiErrorException(response).ConfigureAwait(false); + } + } + + /// + /// Partially changes properties of a view + /// PATCH /_api/view/{view-name}/properties + /// + /// The name or identifier of the view. + /// The body of the request containing required properties. + /// + public virtual async Task PatchViewPropertiesAsync(string viewNameOrId, ViewDetails body) + { + string uri = $"{_apiPath}/{viewNameOrId}/properties"; + var content = GetContent(body, new ApiClientSerializationOptions(true, true)); + using (var response = await _transport.PatchAsync(uri, content).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return DeserializeJsonFromStream(stream); + } + throw await GetApiErrorException(response).ConfigureAwait(false); + } + } + + /// + /// Changes all properties of a view + /// PUT /_api/view/{view-name}/properties + /// + /// The name of the view. + /// The body of the request containing required properties. + /// + public virtual async Task PutViewPropertiesAsync(string viewName, ViewDetails body) + { + string uri = $"{_apiPath}/{viewName}/properties"; + var content = GetContent(body, new ApiClientSerializationOptions(true, true)); + using (var response = await _transport.PutAsync(uri, content).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return DeserializeJsonFromStream(stream); + } + throw await GetApiErrorException(response).ConfigureAwait(false); + } + } + + /// + /// Renames a view + /// PUT /_api/view/{view-name}/rename + /// + /// The name of the view. + /// The body of the request containing required properties. + /// + public virtual async Task PutRenameViewAsync(string viewName, PutRenameViewBody body) + { + string uri = $"{_apiPath}/{viewName}/rename"; + var content = GetContent(body, new ApiClientSerializationOptions(true, true)); + using (var response = await _transport.PutAsync(uri, content).ConfigureAwait(false)) + { + if (response.IsSuccessStatusCode) + { + var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + return DeserializeJsonFromStream(stream); + } + throw await GetApiErrorException(response).ConfigureAwait(false); + } + } + } +} \ No newline at end of file diff --git a/project/roadmap.md b/project/roadmap.md index b1bbc714..f76f4458 100644 --- a/project/roadmap.md +++ b/project/roadmap.md @@ -208,6 +208,17 @@ A tick indicates an item is implemented and has automated tests in place. - [X] `GET/_api/collection/{collection-name}/shards` Return the shard ids of a collection - [X] `PUT/_api/collection/{collection-name}/compact` Compact a collection +#### Views API + +- [X] `GET/_api/view` Reads all views +- [X] `POST/_api/view#iresearch` Create iresearch view +- [X] `DELETE/_api/view/{view-name}` Drops a view +- [X] `GET/_api/view/{view-name}` Return information about a view +- [X] `GET/_api/view/{view-name}/properties` Read properties of a view +- [X] `PATCH/_api/view/{view-name}/properties#iresearch` Partially changes properties of an iresearch view +- [X] `PUT/_api/view/{view-name}/properties#iresearch` Change properties of an iresearch view +- [X] `PUT/_api/view/{view-name}/rename` Rename view + #### Analyzers API - [X] `GET/_api/analyzer` List all Analyzers