Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Microsoft.Azure.Search (deprecated) replaced by Azure.Search.Documents #1794

Merged
merged 4 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 8 additions & 19 deletions core/Piranha.Azure.Search/Content.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,15 @@

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.Azure.Search;
using Microsoft.Azure.Search.Models;
using Microsoft.Spatial;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Piranha.Models;

namespace Piranha.Azure.Search
{
/// <summary>
/// Search index model for Azure Search.
/// </summary>
[SerializePropertyNamesAsCamelCase]
public class Content
{
/// <summary>
Expand All @@ -32,46 +30,37 @@ public class Content
/// <summary>
/// Gets/sets the content slug.
/// </summary>
[IsSearchable]
[Analyzer(AnalyzerName.AsString.StandardLucene)]
[SearchableField(AnalyzerName = LexicalAnalyzerName.Values.StandardLucene)]
public string Slug { get; set; }

/// <summary>
/// Gets/sets the content type.
/// </summary>
[IsFilterable]
[SimpleField(IsFilterable = true)]
public string ContentType { get; set; }

/// <summary>
/// Gets/sets the main title.
/// </summary>
[IsSearchable]
[IsSortable]
[Analyzer(AnalyzerName.AsString.StandardLucene)]
[SearchableField(AnalyzerName = LexicalAnalyzerName.Values.StandardLucene, IsSortable = true)]
public string Title { get; set; }

/// <summary>
/// Gets/sets the optional category.
/// </summary>
[IsFilterable]
[IsSearchable]
[IsSortable]
[Analyzer(AnalyzerName.AsString.StandardLucene)]
[SearchableField(AnalyzerName = LexicalAnalyzerName.Values.StandardLucene, IsFilterable = true, IsSortable = true)]
public string Category { get; set; }

/// <summary>
/// Gets/sets the optional tags.
/// </summary>
[IsFilterable]
[IsSearchable]
[Analyzer(AnalyzerName.AsString.StandardLucene)]
[SearchableField(AnalyzerName = LexicalAnalyzerName.Values.StandardLucene, IsFilterable = true, IsFacetable = true)]
public IList<string> Tags { get; set; } = new List<string>();

/// <summary>
/// Gets/sets the main body.
/// </summary>
[IsSearchable]
[Analyzer(AnalyzerName.AsString.StandardLucene)]
[SearchableField(AnalyzerName = LexicalAnalyzerName.Values.StandardLucene)]
public string Body { get; set; }
}
}
2 changes: 1 addition & 1 deletion core/Piranha.Azure.Search/Piranha.Azure.Search.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Search.Documents" Version="11.3.0" />
<PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.22" />
<PackageReference Include="Microsoft.Azure.Search" Version="10.1.0" />
</ItemGroup>

<ItemGroup>
Expand Down
14 changes: 8 additions & 6 deletions core/Piranha.Azure.Search/PiranhaSearchExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ public static class PiranhaSearchExtensions
/// Adds the Azure Search module.
/// </summary>
/// <param name="serviceBuilder">The service builder</param>
/// <param name="serviceName">The unique name of the azure search service</param>
/// <param name="serviceUrl">The url of the azure search service</param>
/// <param name="apiKey">The admin api key</param>
/// <param name="index">The name of the search index</param>
/// <returns>The services</returns>
public static PiranhaServiceBuilder UseAzureSearch(this PiranhaServiceBuilder serviceBuilder,
string serviceName, string apiKey)
string serviceUrl, string apiKey, string index)
{
serviceBuilder.Services.AddPiranhaAzureSearch(serviceName, apiKey);
serviceBuilder.Services.AddPiranhaAzureSearch(serviceUrl, apiKey, index);

return serviceBuilder;
}
Expand All @@ -34,17 +35,18 @@ public static PiranhaServiceBuilder UseAzureSearch(this PiranhaServiceBuilder se
/// Adds the Azure Search module.
/// </summary>
/// <param name="services">The current service collection</param>
/// <param name="serviceName">The unique name of the azure search service</param>
/// <param name="serviceUrl">The url of the azure search service</param>
/// <param name="apiKey">The admin api key</param>
/// <param name="index">The name of the search index</param>
/// <returns>The services</returns>
public static IServiceCollection AddPiranhaAzureSearch(this IServiceCollection services,
string serviceName, string apiKey)
string serviceUrl, string apiKey, string index)
{
// Add the identity module
App.Modules.Register<Module>();

// Register the search service
services.AddSingleton<ISearch>(new AzureSearchService(serviceName, apiKey));
services.AddSingleton<ISearch>(new AzureSearchService(serviceUrl, apiKey, index));

return services;
}
Expand Down
192 changes: 93 additions & 99 deletions core/Piranha.Azure.Search/Services/AzureSearchService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@
*
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Azure.Search;
using Microsoft.Azure.Search.Models;
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Azure.Search.Documents.Models;
using Piranha.Extend;
using Piranha.Models;

Expand All @@ -25,37 +29,38 @@ namespace Piranha.Azure.Search.Services
/// </summary>
public class AzureSearchService : ISearch
{
private readonly string _serviceName = "";
private readonly string _serviceUrl = "";
private readonly string _apiKey = "";
private readonly string _index = "";

/// <summary>
/// Default constructor.
/// </summary>
/// <param name="serviceName">The search service name</param>
/// <param name="serviceUrl">The search service url</param>
/// <param name="apiKey">The admin api key</param>
public AzureSearchService(string serviceName, string apiKey)
/// <param name="index">Name of the search index</param>
public AzureSearchService(string serviceUrl, string apiKey, string index)
{
_serviceName = serviceName;
_serviceUrl = serviceUrl;
_apiKey = apiKey;
_index = index.ToLowerInvariant();

// Make sure the search indexes are up to date
CreateIndexes();
CreateIndex(_index);
}

/// <summary>
/// Creates the main search indexes.
/// </summary>
public void CreateIndexes()
private void CreateIndex(string indexName)
{
using (var client = CreateClient())
{
var contentIndex = new Index()
{
Name = "content",
Fields = FieldBuilder.BuildForType<Content>()
};
client.Indexes.CreateOrUpdate(contentIndex);
}
var indexClient = CreateSearchIndexClient();
FieldBuilder fieldBuilder = new FieldBuilder();
var searchFields = fieldBuilder.Build(typeof(Content));

var definition = new SearchIndex(indexName, searchFields);

indexClient.CreateOrUpdateIndex(definition);
}

/// <summary>
Expand All @@ -65,41 +70,36 @@ public void CreateIndexes()
/// <param name="page">The page</param>
public async Task SavePageAsync(PageBase page)
{
using (var client = CreateClient())
{
var indexClient = client.Indexes.GetClient("content");
var body = new StringBuilder();

foreach (var block in page.Blocks)
{
if (block is ISearchable searchableBlock)
{
body.AppendLine(searchableBlock.GetIndexedContent());
}
}

var cleanHtml = new Regex("<[^>]*(>|$)");
var cleanSpaces = new Regex("[\\s\\r\\n]+");
var client = CreateSearchClient();

var cleaned = cleanSpaces.Replace(cleanHtml.Replace(body.ToString(), " "), " ").Trim();
var body = new StringBuilder();

var actions = new IndexAction<Content>[]
foreach (var block in page.Blocks)
{
if (block is ISearchable searchableBlock)
{
IndexAction.MergeOrUpload(
new Content
{
Slug = page.Slug,
ContentId = page.Id.ToString(),
ContentType = "page",
Title = page.Title,
Body = cleaned
}
)
};
var batch = IndexBatch.New(actions);

await indexClient.Documents.IndexAsync(batch);
body.AppendLine(searchableBlock.GetIndexedContent());
}
}

var cleanHtml = new Regex("<[^>]*(>|$)");
var cleanSpaces = new Regex("[\\s\\r\\n]+");

var cleaned = cleanSpaces.Replace(cleanHtml.Replace(body.ToString(), " "), " ").Trim();

IndexDocumentsBatch<Content> batch = IndexDocumentsBatch.Create(
IndexDocumentsAction.MergeOrUpload(
new Content
{
Slug = page.Slug,
ContentId = page.Id.ToString(),
ContentType = "page",
Title = page.Title,
Body = cleaned
}
)
);
await client.IndexDocumentsAsync(batch);
}

/// <summary>
Expand All @@ -108,14 +108,9 @@ public async Task SavePageAsync(PageBase page)
/// <param name="page">The page to delete</param>
public async Task DeletePageAsync(PageBase page)
{
using (var client = CreateClient())
{
var indexClient = client.Indexes.GetClient("content");

var batch = IndexBatch.Delete("contentId", new List<string> { page.Id.ToString() });

await indexClient.Documents.IndexAsync(batch);
}
var client = CreateSearchClient();
var batch = IndexDocumentsBatch.Delete("contentId", new List<string> { page.Id.ToString() });
await client.IndexDocumentsAsync(batch);
}

/// <summary>
Expand All @@ -125,43 +120,37 @@ public async Task DeletePageAsync(PageBase page)
/// <param name="post">The post</param>
public async Task SavePostAsync(PostBase post)
{
using (var client = CreateClient())
{
var indexClient = client.Indexes.GetClient("content");
var body = new StringBuilder();
var client = CreateSearchClient();
var body = new StringBuilder();

foreach (var block in post.Blocks)
foreach (var block in post.Blocks)
{
if (block is ISearchable searchableBlock)
{
if (block is ISearchable searchableBlock)
{
body.AppendLine(searchableBlock.GetIndexedContent());
}
body.AppendLine(searchableBlock.GetIndexedContent());
}

var cleanHtml = new Regex("<[^>]*(>|$)");
var cleanSpaces = new Regex("[\\s\\r\\n]+");

var cleaned = cleanSpaces.Replace(cleanHtml.Replace(body.ToString(), " "), " ").Trim();

var actions = new IndexAction<Content>[]
{
IndexAction.MergeOrUpload(
new Content
{
Slug = post.Slug,
ContentId = post.Id.ToString(),
ContentType = "post",
Title = post.Title,
Category = post.Category.Title,
Tags = post.Tags.Select(t => t.Title).ToList(),
Body = cleaned
}
)
};
var batch = IndexBatch.New(actions);

await indexClient.Documents.IndexAsync(batch);
}

var cleanHtml = new Regex("<[^>]*(>|$)");
var cleanSpaces = new Regex("[\\s\\r\\n]+");

var cleaned = cleanSpaces.Replace(cleanHtml.Replace(body.ToString(), " "), " ").Trim();

IndexDocumentsBatch<Content> batch = IndexDocumentsBatch.Create(
IndexDocumentsAction.MergeOrUpload(
new Content
{
Slug = post.Slug,
ContentId = post.Id.ToString(),
ContentType = "post",
Title = post.Title,
Category = post.Category.Title,
Tags = post.Tags.Select(t => t.Title).ToList(),
Body = cleaned
}
)
);
await client.IndexDocumentsAsync(batch);
}

/// <summary>
Expand All @@ -170,22 +159,27 @@ public async Task SavePostAsync(PostBase post)
/// <param name="post">The post to delete</param>
public async Task DeletePostAsync(PostBase post)
{
using (var client = CreateClient())
{
var indexClient = client.Indexes.GetClient("content");

var batch = IndexBatch.Delete("contentId", new List<string> { post.Id.ToString() });
var client = CreateSearchClient();
var batch = IndexDocumentsBatch.Delete("contentId", new List<string> { post.Id.ToString() });
await client.IndexDocumentsAsync(batch);
}

await indexClient.Documents.IndexAsync(batch);
}
/// <summary>
/// Creates the SearchIndexClient.
/// </summary>
private SearchIndexClient CreateSearchIndexClient()
{
SearchIndexClient indexClient = new SearchIndexClient(new Uri(_serviceUrl), new AzureKeyCredential(_apiKey));
return indexClient;
}

/// <summary>
/// Creates the search client.
/// Creates the SearchClient.
/// </summary>
private SearchServiceClient CreateClient()
private SearchClient CreateSearchClient()
{
return new SearchServiceClient(_serviceName, new SearchCredentials(_apiKey));
SearchClient searchClient = new SearchClient(new Uri(_serviceUrl), _index, new AzureKeyCredential(_apiKey));
return searchClient;
}
}
}