Skip to content

Commit

Permalink
Add some field attributes search docs and SortableTitle to search ind…
Browse files Browse the repository at this point in the history
…ex (#447)

Existing search service treats an empty string title as missing so package ID is used instead of title for the sortable title field.
  • Loading branch information
joelverhagen committed Dec 12, 2018
1 parent 141e77a commit 9d2799e
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 45 deletions.
21 changes: 19 additions & 2 deletions src/NuGet.Services.AzureSearch/DocumentUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ internal static class DocumentUtilities
NuGetFramework.UnsupportedFramework
};

public static string GetSearchFilterString(SearchFilters searchFilters)
{
return searchFilters.ToString();
}

public static void PopulateMetadata(
IBaseMetadataDocument document,
string packageId,
Expand Down Expand Up @@ -55,6 +60,7 @@ public static void PopulateMetadata(
document.ReleaseNotes = package.ReleaseNotes;
document.RequiresLicenseAcceptance = package.RequiresLicenseAcceptance;
document.SemVerLevel = package.SemVerLevelKey;
document.SortableTitle = GetSortableTitle(package.Title, packageId);
document.Summary = package.Summary;
document.Tags = Utils.SplitTags(package.Tags ?? string.Empty);
document.Title = package.Title;
Expand Down Expand Up @@ -85,18 +91,29 @@ public static void PopulateMetadata(
document.ProjectUrl = leaf.ProjectUrl;
document.Published = leaf.Published;
document.ReleaseNotes = leaf.ReleaseNotes;
document.RequiresLicenseAcceptance = leaf.RequireLicenseAgreement;
document.RequiresLicenseAcceptance = leaf.RequireLicenseAgreement ?? false;
document.SemVerLevel = leaf.IsSemVer2() ? 2 : (int?)null;
document.SortableTitle = GetSortableTitle(leaf.Title, leaf.PackageId);
document.Summary = leaf.Summary;
document.Tags = leaf.Tags == null ? null : leaf.Tags.ToArray();
document.Title = leaf.Title;
}

private static string GetSortableTitle(string title, string packageId)
{
if (string.IsNullOrWhiteSpace(title))
{
return packageId;
}

return title;
}

public static string GetSearchDocumentKey(string packageId, SearchFilters searchFilters)
{
var lowerId = packageId.ToLowerInvariant();
var encodedId = EncodeKey(lowerId);
return $"{encodedId}-{searchFilters}";
return $"{encodedId}-{GetSearchFilterString(searchFilters)}";
}

public static string GetHijackDocumentKey(string packageId, string normalizedVersion)
Expand Down
15 changes: 2 additions & 13 deletions src/NuGet.Services.AzureSearch/HijackDocumentBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public HijackDocument.Full Full(
{
var document = new HijackDocument.Full();

PopulateFull(document, leaf.PackageId, normalizedVersion, changes, leaf.Title);
PopulateLatest(document, leaf.PackageId, normalizedVersion, changes);
DocumentUtilities.PopulateMetadata(document, normalizedVersion, leaf);

return document;
Expand All @@ -51,23 +51,12 @@ public HijackDocument.Full Full(
{
var document = new HijackDocument.Full();

PopulateFull(document, packageId, package.NormalizedVersion, changes, package.Title);
PopulateLatest(document, packageId, package.NormalizedVersion, changes);
DocumentUtilities.PopulateMetadata(document, packageId, package);

return document;
}

private static void PopulateFull(
HijackDocument.Full document,
string packageId,
string normalizedVersion,
HijackDocumentChanges changes,
string title)
{
PopulateLatest(document, packageId, normalizedVersion, changes);
document.SortableTitle = title ?? packageId;
}

private static void PopulateLatest<T>(
T document,
string packageId,
Expand Down
35 changes: 30 additions & 5 deletions src/NuGet.Services.AzureSearch/Models/BaseMetadataDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,64 @@

using System;
using Microsoft.Azure.Search;
using Microsoft.Azure.Search.Models;

namespace NuGet.Services.AzureSearch
{
/// <summary>
/// Implements most of <see cref="IBaseMetadataDocument"/>. Some fields are not defined here since they have
/// different Azure Search attributes.
/// </summary>
public abstract class BaseMetadataDocument : KeyedDocument
public abstract class BaseMetadataDocument : KeyedDocument, IBaseMetadataDocument
{
[IsFilterable]
public int? SemVerLevel { get; set; }

[IsSearchable]
public string Authors { get; set; }

public string Copyright { get; set; }
public DateTimeOffset? Created { get; set; }

[IsSearchable]
public string Description { get; set; }

public long? FileSize { get; set; }
public string FlattenedDependencies { get; set; }
public string Hash { get; set; }
public string HashAlgorithm { get; set; }
public string IconUrl { get; set; }
public string Language { get; set; }

[IsSortable]
public DateTimeOffset? LastEdited { get; set; }

public string LicenseUrl { get; set; }
public string MinClientVersion { get; set; }

[IsSearchable]
public string NormalizedVersion { get; set; }

public string OriginalVersion { get; set; }

[IsSearchable]
public string PackageId { get; set; }

public bool? Prerelease { get; set; }
public string ProjectUrl { get; set; }

[IsSortable]
public DateTimeOffset? Published { get; set; }

public string ReleaseNotes { get; set; }
public bool? RequiresLicenseAcceptance { get; set; }

[IsSortable]
public string SortableTitle { get; set; }

[IsSearchable]
public string Summary { get; set; }

[IsSearchable]
public string[] Tags { get; set; }

[IsSearchable]
public string Title { get; set; }
}
}
7 changes: 0 additions & 7 deletions src/NuGet.Services.AzureSearch/Models/HijackDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,6 @@ public static class HijackDocument
[SerializePropertyNamesAsCamelCase]
public class Full : BaseMetadataDocument, ILatest, IBaseMetadataDocument
{
[IsSortable]
public DateTimeOffset? LastEdited { get; set; }
[IsSortable]
public DateTimeOffset? Published { get; set; }
[IsSortable]
public string SortableTitle { get; set; }

public bool? IsLatestStableSemVer1 { get; set; }
public bool? IsLatestSemVer1 { get; set; }
public bool? IsLatestStableSemVer2 { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ public interface IBaseMetadataDocument
string OriginalVersion { get; set; }
string PackageId { get; set; }
bool? Prerelease { get; set; }
DateTimeOffset? Published { get; set; }
string ProjectUrl { get; set; }
DateTimeOffset? Published { get; set; }
string ReleaseNotes { get; set; }
bool? RequiresLicenseAcceptance { get; set; }
int? SemVerLevel { get; set; }
string SortableTitle { get; set; }
string Summary { get; set; }
string[] Tags { get; set; }
string Title { get; set; }
Expand Down
5 changes: 2 additions & 3 deletions src/NuGet.Services.AzureSearch/Models/SearchDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class Full : AddFirst
[SerializePropertyNamesAsCamelCase]
public class AddFirst : UpdateLatest
{
[IsSearchable]
public string[] Owners { get; set; }
}

Expand All @@ -37,14 +38,12 @@ public class AddFirst : UpdateLatest
/// <see cref="SearchIndexChangeType.DowngradeLatest"/>.
/// </summary>
[SerializePropertyNamesAsCamelCase]
public class UpdateLatest : BaseMetadataDocument, IVersions, IBaseMetadataDocument
public class UpdateLatest : BaseMetadataDocument, IVersions
{
[IsFilterable]
public string SearchFilters { get; set; }

public string FullVersion { get; set; }
public DateTimeOffset? LastEdited { get; set; }
public DateTimeOffset? Published { get; set; }
public string[] Versions { get; set; }
public bool? IsLatestStable { get; set; }
public bool? IsLatest { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion src/NuGet.Services.AzureSearch/SearchDocumentBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ private static void PopulateUpdateLatest(
string fullVersion)
{
PopulateVersions(document, packageId, searchFilters, versions, isLatestStable, isLatest);
document.SearchFilters = searchFilters.ToString();
document.SearchFilters = DocumentUtilities.GetSearchFilterString(searchFilters);
document.FullVersion = fullVersion;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NuGet.Services.AzureSearch.Support;
using Xunit;
Expand Down Expand Up @@ -63,11 +64,12 @@ public async Task SetsExpectedProperties()
Assert.Equal(_fullJson, json);
}

[Fact]
public void UsesIdForNullTitleInHijackIndex()
[Theory]
[MemberData(nameof(MissingTitles))]
public void UsesIdWhenMissingForSortableTitle(string title)
{
var package = Data.PackageEntity;
package.Title = null;
package.Title = title;

var document = _target.Full(Data.PackageId, _changes, package);

Expand Down Expand Up @@ -137,15 +139,28 @@ public async Task SetsExpectedProperties()
Assert.Equal(_fullJson, json);
}

[Fact]
public void UsesIdForNullTitleInHijackIndex()
[Theory]
[MemberData(nameof(MissingTitles))]
public void UsesIdWhenMissingForSortableTitle(string title)
{
var leaf = Data.Leaf;
leaf.Title = null;
leaf.Title = title;

var document = _target.Full(Data.NormalizedVersion, _changes, leaf);

Assert.Equal(Data.PackageId, document.SortableTitle);
}

[Fact]
public void DefaultsRequiresLicenseAcceptanceToFalse()
{
var leaf = Data.Leaf;
leaf.RequireLicenseAgreement = null;

var document = _target.Full(Data.NormalizedVersion, _changes, leaf);

Assert.False(document.RequiresLicenseAcceptance);
}
}

public abstract class BaseFacts
Expand All @@ -154,6 +169,14 @@ public abstract class BaseFacts
protected readonly string _fullJson;
protected readonly HijackDocumentBuilder _target;

public static IEnumerable<object[]> MissingTitles = new[]
{
new object[] { null },
new object[] { string.Empty },
new object[] { " " },
new object[] { " \t"},
};

public BaseFacts()
{
_changes = new HijackDocumentChanges(
Expand All @@ -167,9 +190,6 @@ public BaseFacts()
""value"": [
{
""@search.action"": ""upload"",
""lastEdited"": ""2017-01-02T00:00:00+00:00"",
""published"": ""2017-01-03T00:00:00+00:00"",
""sortableTitle"": ""Windows Azure Storage"",
""isLatestStableSemVer1"": false,
""isLatestSemVer1"": true,
""isLatestStableSemVer2"": false,
Expand All @@ -185,15 +205,18 @@ public BaseFacts()
""hashAlgorithm"": ""SHA512"",
""iconUrl"": ""http://go.microsoft.com/fwlink/?LinkID=288890"",
""language"": ""en-US"",
""lastEdited"": ""2017-01-02T00:00:00+00:00"",
""licenseUrl"": ""http://go.microsoft.com/fwlink/?LinkId=331471"",
""minClientVersion"": ""2.12"",
""normalizedVersion"": ""7.1.2-alpha"",
""originalVersion"": ""7.1.2.0-alpha+git"",
""packageId"": ""WindowsAzure.Storage"",
""prerelease"": true,
""projectUrl"": ""https://github.com/Azure/azure-storage-net"",
""published"": ""2017-01-03T00:00:00+00:00"",
""releaseNotes"": ""Release notes."",
""requiresLicenseAcceptance"": true,
""sortableTitle"": ""Windows Azure Storage"",
""summary"": ""Summary."",
""tags"": [
""Microsoft"",
Expand Down
Loading

0 comments on commit 9d2799e

Please sign in to comment.