Skip to content

Commit

Permalink
Merge pull request #357 from arangodb/feature-3.8/DE-201-support-for-…
Browse files Browse the repository at this point in the history
…analyzers

Support for analyzers
  • Loading branch information
Zyqsempai authored Apr 28, 2022
2 parents cc473b4 + 4bb9408 commit 5f08f11
Show file tree
Hide file tree
Showing 14 changed files with 573 additions and 3 deletions.
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
- run:
name: Test
command:
dotnet test -c Release --filter "Feature!=StreamTransaction&RunningMode!=Cluster"
dotnet test -c Release --filter "Feature!=StreamTransaction&RunningMode!=Cluster&Feature!=Analyzer"

"test-arangodb-3_5":
working_directory: ~/arangodb-net-standard
Expand All @@ -80,7 +80,7 @@ jobs:
- run:
name: Test
command:
dotnet test -c Release --filter RunningMode!=Cluster
dotnet test -c Release --filter "RunningMode!=Cluster"

"test-arangodb-3_6":
working_directory: ~/arangodb-net-standard
Expand All @@ -99,7 +99,7 @@ jobs:
- run:
name: Test
command:
dotnet test -c Release --filter RunningMode!=Cluster
dotnet test -c Release --filter "RunningMode!=Cluster"

"test-arangodb-3_7":
working_directory: ~/arangodb-net-standard
Expand Down
152 changes: 152 additions & 0 deletions arangodb-net-standard.Test/AnalyzerApi/AnalyzerApiClientTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using ArangoDBNetStandard;
using ArangoDBNetStandard.AnalyzerApi;
using ArangoDBNetStandard.AnalyzerApi.Models;
using ArangoDBNetStandard.Transport;
using Moq;
using Xunit;

namespace ArangoDBNetStandardTest.IndexApi
{
public class AnalyzerApiClientTest : IClassFixture<AnalyzerApiClientTestFixture>, IAsyncLifetime
{
private AnalyzerApiClient _analyzerApi;
private ArangoDBClient _adb;

public AnalyzerApiClientTest(AnalyzerApiClientTestFixture fixture)
{
_adb = fixture.ArangoDBClient;
_analyzerApi = _adb.Analyzer;
}

public Task InitializeAsync()
{
return Task.CompletedTask;
}

public Task DisposeAsync()
{
return Task.CompletedTask;
}

[Fact]
[Trait("Feature", "Analyzer")]
public async Task GetAllAnalyzersAsync_ShouldSucceed()
{
var res = await _analyzerApi.GetAllAnalyzersAsync();
Assert.Equal(HttpStatusCode.OK, res.Code);
Assert.False(res.Error);
}

[Fact]
[Trait("Feature", "Analyzer")]
public async Task PostAnalyzerAsync_ShouldSucceed()
{
var res = await _analyzerApi.PostAnalyzerAsync(
new Analyzer()
{
Name = "text_sc",
Type = "identity",
Properties = new AnalyzerProperties()
{
Accent = false,
Case = "lower",
Locale = "sc",
Stemming = false,
StopWords = new List<string>()
},
Features = new List<string>()
{
"frequency",
"position",
"norm"
}
}
);
Assert.NotNull(res);
Assert.NotNull(res.Name);
}

[Fact]
[Trait("Feature", "Analyzer")]
public async Task PostAnalyzerAsync_ShouldThrow_WhenAnalyzerIsInvalid()
{
try
{
//This call should fail because...
var res = await _analyzerApi.PostAnalyzerAsync(
new Analyzer()
{
Name = "text_sc",
Type = "collection", //...invalid analyzer type
Properties = new AnalyzerProperties()
{
Accent = false,
Case = "lower",
Locale = "sc",
Stemming = false,
StopWords = new List<string>()
},
Features = new List<string>()
{
"frequency",
"position",
"norm"
}
}
);
}
catch (ApiErrorException ex)
{
Assert.NotNull(ex);
Assert.NotNull(ex.ApiError);
Assert.True(ex.ApiError.Error);
}
}

[Fact]
[Trait("Feature", "Analyzer")]
public async Task GetAnalyzerAsync_ShouldSucceed()
{
var allRes = await _analyzerApi.GetAllAnalyzersAsync();
var firstName = allRes.Result[0].Name;
var res = await _analyzerApi.GetAnalyzerAsync(firstName);
Assert.Equal(HttpStatusCode.OK, res.Code);
Assert.False(res.Error);
}

[Fact]
[Trait("Feature", "Analyzer")]
public async Task DeleteAnalyzerAsync_ShouldSucceed()
{
var name = "text_mu";
var createRes = await _analyzerApi.PostAnalyzerAsync(
new Analyzer()
{
Name = name,
Type = "identity",
Properties = new AnalyzerProperties()
{
Accent = false,
Case = "lower",
Locale = "mu",
Stemming = false,
StopWords = new List<string>()
},
Features = new List<string>()
{
"frequency",
"position",
"norm"
}
}
);
var res = await _analyzerApi.DeleteAnalyzerAsync(name);
Assert.Equal(HttpStatusCode.OK, res.Code);
Assert.False(res.Error);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using ArangoDBNetStandard;
using ArangoDBNetStandard.CollectionApi.Models;
using ArangoDBNetStandard.AnalyzerApi.Models;
using System;
using System.Threading.Tasks;

namespace ArangoDBNetStandardTest.IndexApi
{
public class AnalyzerApiClientTestFixture : ApiClientTestFixtureBase
{
public ArangoDBClient ArangoDBClient { get; internal set; }

public AnalyzerApiClientTestFixture()
{
}

public override async Task InitializeAsync()
{
await base.InitializeAsync();

Console.WriteLine("AnalyzerApiClientTestFixture.InitializeAsync() started.");
string dbName = nameof(AnalyzerApiClientTestFixture);
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;
}

}
}
}
142 changes: 142 additions & 0 deletions arangodb-net-standard/AnalyzerApi/AnalyzerApiClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using System.Net;
using System.Threading.Tasks;

using ArangoDBNetStandard.Serialization;
using ArangoDBNetStandard.Transport;
using ArangoDBNetStandard.AnalyzerApi.Models;
using System;

namespace ArangoDBNetStandard.AnalyzerApi
{
/// <summary>
/// A client for interacting with ArangoDB Analyzer endpoints,
/// implementing <see cref="IAnalyzerApiClient"/>.
/// </summary>
public class AnalyzerApiClient : ApiClientBase, IAnalyzerApiClient
{
/// <summary>
/// The transport client used to communicate with the ArangoDB host.
/// </summary>
protected IApiClientTransport _client;

/// <summary>
/// The root path of the API.
/// </summary>
protected readonly string _analyzerApiPath = "_api/analyzer";

/// <summary>
/// Creates an instance of <see cref="AnalyzerApiClient"/>
/// using the provided transport layer and the default JSON serialization.
/// </summary>
/// <param name="client">Transport client that the API client will use to communicate with ArangoDB</param>
public AnalyzerApiClient(IApiClientTransport client)
: base(new JsonNetApiClientSerialization())
{
_client = client;
}

/// <summary>
/// Creates an instance of <see cref="AnalyzerApiClient"/>
/// using the provided transport and serialization layers.
/// </summary>
/// <param name="client">Transport client that the API client will use to communicate with ArangoDB.</param>
/// <param name="serializer">Serializer to be used.</param>
public AnalyzerApiClient(IApiClientTransport client, IApiClientSerialization serializer)
: base(serializer)
{
_client = client;
}

/// <summary>
/// Fetch the list of available Analyzer definitions.
/// GET /_api/analyzer
/// </summary>
/// <returns></returns>
public virtual async Task<GetAllAnalyzersResponse> GetAllAnalyzersAsync()
{
string uri = _analyzerApiPath;
using (var response = await _client.GetAsync(uri).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<GetAllAnalyzersResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}

/// <summary>
/// Creates a new Analyzer based on the provided definition
/// POST /_api/analyzer
/// </summary>
/// <param name="body">The properties of the new analyzer.</param>
/// <returns></returns>
public virtual async Task<Analyzer> PostAnalyzerAsync(Analyzer body)
{
if (body == null)
{
throw new ArgumentException("body is required", nameof(body));
}
var uri = _analyzerApiPath;
var content = GetContent(body, new ApiClientSerializationOptions(true, true));
using (var response = await _client.PostAsync(uri, content).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<Analyzer>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}

/// <summary>
/// Fetches the definition of the specified analyzer.
/// GET /_api/analyzer/{analyzer-name}
/// </summary>
/// <param name="analyzerName">The name of the analyzer</param>
/// <returns></returns>
public virtual async Task<GetAnalyzerResponse> GetAnalyzerAsync(string analyzerName)
{
if (string.IsNullOrEmpty(analyzerName))
{
throw new ArgumentException("Analyzer name is required", nameof(analyzerName));
}
string uri = _analyzerApiPath + '/' + WebUtility.UrlEncode(analyzerName);
using (var response = await _client.GetAsync(uri).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<GetAnalyzerResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}

/// <summary>
/// Deletes an Analyzer.
/// DELETE /_api/analyzer/{analyzer-name}
/// </summary>
/// <param name="analyzerName">The name of the analyzer</param>
/// <returns></returns>
public virtual async Task<DeleteAnalyzerResponse> DeleteAnalyzerAsync(string analyzerName)
{
if (string.IsNullOrEmpty(analyzerName))
{
throw new ArgumentException("Analyzer name is required", nameof(analyzerName));
}
string uri = _analyzerApiPath + '/' + WebUtility.UrlEncode(analyzerName);
using (var response = await _client.DeleteAsync(uri).ConfigureAwait(false))
{
if (response.IsSuccessStatusCode)
{
var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return DeserializeJsonFromStream<DeleteAnalyzerResponse>(stream);
}
throw await GetApiErrorException(response).ConfigureAwait(false);
}
}
}
}
Loading

0 comments on commit 5f08f11

Please sign in to comment.