Skip to content

Commit

Permalink
Feat/index reusable types (#26)
Browse files Browse the repository at this point in the history
* feat(Azure): update packages and nugets to Xperience 29.3.3

* feat(Indexing-reusable-items): docs

* feat(Indexing-reusable-items): update to XbyK v29.4.2

* feat(repository): add end line, images to gitattributes

* feat(Indexing-reusable-items): reusable content type info

* fix(tests): indexd item model extensions test apply channel check

* fix(admin/client): path item selection description

* feat(Indexing-reusable-items): admin

* feat(Indexing-reusable-items): images

* feat(Indexing-reusable-items): examples

* fix(AzureSearch): formating

* fix(AzureSearch): redundand using

* feat(Indexing-reusable-items): DefaultAzureSearchClient correctly index reusable items
  • Loading branch information
bkapustik authored Sep 24, 2024
1 parent 49e1244 commit cf79502
Show file tree
Hide file tree
Showing 69 changed files with 4,738 additions and 4,548 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* text eol=crlf
*.png binary
*.jpg binary
10 changes: 5 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Azure.Search.Documents" Version="11.6.0-beta.2" />
<PackageVersion Include="Kentico.Xperience.Admin" Version="29.0.0" />
<PackageVersion Include="Kentico.Xperience.WebApp" Version="29.0.0" />
<PackageVersion Include="kentico.xperience.azurestorage" Version="29.0.0" />
<PackageVersion Include="kentico.xperience.imageprocessing" Version="29.0.0" />
<PackageVersion Include="Kentico.Xperience.Core.Tests" Version="29.0.0" />
<PackageVersion Include="Kentico.Xperience.Admin" Version="29.4.2" />
<PackageVersion Include="Kentico.Xperience.WebApp" Version="29.4.2" />
<PackageVersion Include="kentico.xperience.azurestorage" Version="29.4.2" />
<PackageVersion Include="kentico.xperience.imageprocessing" Version="29.4.2" />
<PackageVersion Include="Kentico.Xperience.Core.Tests" Version="29.4.2" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.20.0.85982" />

Expand Down
14 changes: 7 additions & 7 deletions docs/Custom-index-strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class ExampleSearchIndexingStrategy : BaseAzureSearchIndexingStrategy<Sim
return null;
}

result.Title = page?.ArticleTitle ?? "";
result.Title = page?.ArticleTitle ?? string.Empty;
}
else
{
Expand All @@ -78,22 +78,22 @@ Some properties of the `IIndexEventItemModel` are added to the indexed data by d
public class BaseAzureSearchModel : IAzureSearchModel
{
[SearchableField(IsSortable = true, IsFilterable = true, IsFacetable = true)]
public string? Url { get; set; } = "";
public string? Url { get; set; } = string.Empty;

[SearchableField(IsFacetable = true, IsFilterable = true)]
public string ContentTypeName { get; set; } = "";
public string ContentTypeName { get; set; } = string.Empty;

[SearchableField(IsSortable = true, IsFacetable = true, IsFilterable = true)]
public string LanguageName { get; set; } = "";
public string LanguageName { get; set; } = string.Empty;

[SimpleField(IsKey = false)]
public string ItemGuid { get; set; } = "";
public string ItemGuid { get; set; } = string.Empty;

[SimpleField(IsKey = true)]
public string ObjectID { get; set; } = "";
public string ObjectID { get; set; } = string.Empty;

[SimpleField(IsKey = false)]
public string Name { get; set; } = "";
public string Name { get; set; } = string.Empty;
}
```

Expand Down
16 changes: 12 additions & 4 deletions docs/Managing-Indexes.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,24 @@ Fill out the search index form, populating the fields with your custom values.

![Administration search edit form](/images/xperience-administration-search-index-edit-form.jpg)

- Rebuild Hook - for validating a request rebuild of the search index from an external source (ex: API request)
- Indexed Languages - the index will only include content in the selected languages
- Channel Name - the index will only be triggered by web page item creation or modication in the selected website channel
- Index Name - the name of the displayed index.

- Included Reusable Content Types - these are the reusable content types that will be processed by your custom indexing strategy.
If no option is selected, no items will be processed.

- Indexed Languages - the index will only include content in the selected languages.

- Channel Name - the index will only be triggered by web page item creation or modification in the selected website channel.

- Indexing Strategy - the indexing strategy specified in code during dependency registration of a custom indexing strategies.
- If you want the default strategy to appear here, register it explicitly in `IServiceCollection.AddKenticoAzureSearch()` method

- Rebuild Hook - for validating a request rebuild of the search index from an external source (ex: API request).

Now, configure the web page paths and content types that the search index depends on by clicking the Add New Path button
or clicking an existing path in the table at the top of the index configuration form.

![Administration search index list](/images/xperience-administration-search-index-edit-form-paths-edit.jpg)
![Administration search edit paths form](/images/xperience-administration-search-index-edit-form-paths-edit.jpg)

- Included Path - can be an exact relative path of a web page item, (ex: `/path/to/my/page`), or a wildcard path (ex: `/parent-path/%`)
- To determine a web page path, select the web page in the website channel page tree, then view the "Current URL" in the Content tab of the web page. The path will be the relative path excluding the domain
Expand Down
8 changes: 4 additions & 4 deletions docs/Scraping-web-page-content.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class WebCrawlerService
ex,
$"Tree Path: {page.SystemFields.WebPageItemTreePath}");
}
return "";
return string.Empty;
}

public async Task<string> CrawlPage(string url)
Expand All @@ -65,7 +65,7 @@ public class WebCrawlerService
ex,
$"Url: {url}");
}
return "";
return string.Empty;
}
}
```
Expand Down Expand Up @@ -126,8 +126,8 @@ public class WebScraperHtmlSanitizer
textContent = HTMLHelper.RegexHtmlToTextWhiteSpace.Replace(textContent, " ");
textContent = textContent.Trim();

string title = doc.Head?.QuerySelector("title")?.TextContent ?? "";
string description = doc.Head?.QuerySelector("meta[name='description']")?.GetAttribute("content") ?? "";
string title = doc.Head?.QuerySelector("title")?.TextContent ?? string.Empty;
string description = doc.Head?.QuerySelector("meta[name='description']")?.GetAttribute("content") ?? string.Empty;

return string.Join(
" ",
Expand Down
4 changes: 2 additions & 2 deletions docs/Search-index-querying.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ Map Retrieved SearchModel data to a more simple `SearchResultModel`
```csharp
public class SearchResultModel
{
public string Title { get; set; } = "";
public string Url { get; set; } = "";
public string Title { get; set; } = string.Empty;
public string Url { get; set; } = string.Empty;
}
```

Expand Down
4 changes: 2 additions & 2 deletions docs/Semantic-ranking.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public class SemanticRankingSearchStrategy : BaseAzureSearchIndexingStrategy<Dan
return null;
}

result.Title = page?.CafeTitle ?? "";
result.Title = page?.CafeTitle ?? string.Empty;
string rawContent = await webCrawler.CrawlWebPage(page!);
result.Content = htmlSanitizer.SanitizeHtmlDocument(rawContent);
}
Expand All @@ -95,7 +95,7 @@ public class SemanticRankingSearchStrategy : BaseAzureSearchIndexingStrategy<Dan
return null;
}

result.Title = page?.ArticleTitle ?? "";
result.Title = page?.ArticleTitle ?? string.Empty;
string rawContent = await webCrawler.CrawlWebPage(page!);
result.Content = htmlSanitizer.SanitizeHtmlDocument(rawContent);
}
Expand Down
10 changes: 5 additions & 5 deletions docs/Using-OData-geo-spatial-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ public class GeoLocationSearchStrategy : BaseAzureSearchIndexingStrategy<GeoLoca
return null;
}

result.Title = page?.CafeTitle ?? "";
result.Location = page?.CafeLocation ?? "";
result.Title = page?.CafeTitle ?? string.Empty;
result.Location = page?.CafeLocation ?? string.Empty;

//We can use this value later to sort by distance from the user accessing our search page.
//Example for this scenario is shown in DancingGoatSearchService.GeoSearch
Expand Down Expand Up @@ -144,9 +144,9 @@ Map Retrieved SearchModel data to a more simple `GeoLocationSearchResult`
```csharp
public class GeoLocationSearchResult
{
public string Title { get; set; } = "";
public string Url { get; set; } = "";
public string Location { get; set; } = "";
public string Title { get; set; } = string.Empty;
public string Url { get; set; } = string.Empty;
public string Location { get; set; } = string.Empty;
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static IServiceCollection AddKenticoAzureSearchServices(this IServiceColl
builder.RegisterStrategy<DancingGoatSimpleSearchStrategy, DancingGoatSimpleSearchModel>(nameof(DancingGoatSimpleSearchStrategy));
builder.RegisterStrategy<GeoLocationSearchStrategy, GeoLocationSearchModel>(nameof(GeoLocationSearchStrategy));
builder.RegisterStrategy<CustomItemsReindexingSearchStrategy, DancingGoatSearchModel>(nameof(CustomItemsReindexingSearchStrategy));
builder.RegisterStrategy<ReusableContentItemsIndexingStrategy, DancingGoatSearchModel>(nameof(ReusableContentItemsIndexingStrategy));
}, configuration);

services.AddTransient<DancingGoatSearchService>();
Expand Down
4 changes: 2 additions & 2 deletions examples/DancingGoat/Search/Models/DancingGoatSearchResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

public class DancingGoatSearchResult
{
public string Title { get; set; } = "";
public string Url { get; set; } = "";
public string Title { get; set; } = string.Empty;
public string Url { get; set; } = string.Empty;
}
6 changes: 3 additions & 3 deletions examples/DancingGoat/Search/Models/GeoLocationSearchResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public class GeoLocationSearchResult
{
public string Title { get; set; } = "";
public string Url { get; set; } = "";
public string Location { get; set; } = "";
public string Title { get; set; } = string.Empty;
public string Url { get; set; } = string.Empty;
public string Location { get; set; } = string.Empty;
}
4 changes: 2 additions & 2 deletions examples/DancingGoat/Search/Services/WebCrawlerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public async Task<string> CrawlWebPage(IWebPageFieldsSource page)
ex,
$"Tree Path: {page.SystemFields.WebPageItemTreePath}");
}
return "";
return string.Empty;
}

public async Task<string> CrawlPage(string url)
Expand All @@ -62,6 +62,6 @@ public async Task<string> CrawlPage(string url)
ex,
$"Url: {url}");
}
return "";
return string.Empty;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,70 +87,67 @@ public override async Task<IAzureSearchModel> MapToAzureSearchModelOrNull(IIndex

// IIndexEventItemModel could be a reusable content item or a web page item, so we use
// pattern matching to get access to the web page item specific type and fields
if (item is IndexEventWebPageItemModel indexedPage)
if (item is not IndexEventWebPageItemModel indexedPage)
{
if (string.Equals(item.ContentTypeName, CafePage.CONTENT_TYPE_NAME, StringComparison.OrdinalIgnoreCase))
return null;
}
if (string.Equals(item.ContentTypeName, CafePage.CONTENT_TYPE_NAME, StringComparison.OrdinalIgnoreCase))
{
// The implementation of GetPage<T>() is below
var page = await strategyHelper.GetPage<CafePage>(
indexedPage.ItemGuid,
indexedPage.WebsiteChannelName,
indexedPage.LanguageName,
CafePage.CONTENT_TYPE_NAME);

if (page is null)
{
// The implementation of GetPage<T>() is below
var page = await strategyHelper.GetPage<CafePage>(
indexedPage.ItemGuid,
indexedPage.WebsiteChannelName,
indexedPage.LanguageName,
CafePage.CONTENT_TYPE_NAME);

if (page is null)
{
return null;
}

result.Title = page?.CafeTitle ?? "";
string rawContent = await webCrawler.CrawlWebPage(page!);
result.Content = htmlSanitizer.SanitizeHtmlDocument(rawContent);
return null;
}
else if (string.Equals(item.ContentTypeName, ArticlePage.CONTENT_TYPE_NAME, StringComparison.OrdinalIgnoreCase))

result.Title = page?.CafeTitle ?? string.Empty;
string rawContent = await webCrawler.CrawlWebPage(page!);
result.Content = htmlSanitizer.SanitizeHtmlDocument(rawContent);
}
else if (string.Equals(item.ContentTypeName, ArticlePage.CONTENT_TYPE_NAME, StringComparison.OrdinalIgnoreCase))
{
// The implementation of GetPage<T>() is below
var page = await strategyHelper.GetPage<ArticlePage>(
indexedPage.ItemGuid,
indexedPage.WebsiteChannelName,
indexedPage.LanguageName,
ArticlePage.CONTENT_TYPE_NAME);

if (page is null)
{
// The implementation of GetPage<T>() is below
var page = await strategyHelper.GetPage<ArticlePage>(
indexedPage.ItemGuid,
indexedPage.WebsiteChannelName,
indexedPage.LanguageName,
ArticlePage.CONTENT_TYPE_NAME);

if (page is null)
{
return null;
}

result.Title = page?.ArticleTitle ?? "";
string rawContent = await webCrawler.CrawlWebPage(page!);
result.Content = htmlSanitizer.SanitizeHtmlDocument(rawContent);
return null;
}
else if (string.Equals(item.ContentTypeName, HomePage.CONTENT_TYPE_NAME, StringComparison.OrdinalIgnoreCase))

result.Title = page?.ArticleTitle ?? string.Empty;
string rawContent = await webCrawler.CrawlWebPage(page!);
result.Content = htmlSanitizer.SanitizeHtmlDocument(rawContent);
}
else if (string.Equals(item.ContentTypeName, HomePage.CONTENT_TYPE_NAME, StringComparison.OrdinalIgnoreCase))
{
var page = await strategyHelper.GetPage<HomePage>(
indexedPage.ItemGuid,
indexedPage.WebsiteChannelName,
indexedPage.LanguageName,
HomePage.CONTENT_TYPE_NAME);

if (page is null)
{
var page = await strategyHelper.GetPage<HomePage>(
indexedPage.ItemGuid,
indexedPage.WebsiteChannelName,
indexedPage.LanguageName,
HomePage.CONTENT_TYPE_NAME);

if (page is null)
{
return null;
}

if (page.HomePageBanner.IsNullOrEmpty())
{
return null;
}

result.Title = page!.HomePageBanner.First().BannerHeaderText;
string rawContent = await webCrawler.CrawlWebPage(page!);
result.Content = htmlSanitizer.SanitizeHtmlDocument(rawContent);
return null;
}
else

if (page.HomePageBanner.IsNullOrEmpty())
{
return null;
}

result.Title = page!.HomePageBanner.First().BannerHeaderText;
string rawContent = await webCrawler.CrawlWebPage(page!);
result.Content = htmlSanitizer.SanitizeHtmlDocument(rawContent);
}
else
{
Expand Down
Loading

0 comments on commit cf79502

Please sign in to comment.