Skip to content

Commit bac47c4

Browse files
Implement similar document search
1 parent 4f8d55b commit bac47c4

File tree

5 files changed

+211
-0
lines changed

5 files changed

+211
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Net.Http.Json;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace Meilisearch
6+
{
7+
public partial class Index
8+
{
9+
/// <summary>
10+
/// Search for similar documents.
11+
/// </summary>
12+
/// <param name="query">The query to search for similar documents.</param>
13+
/// <param name="cancellationToken">The cancellation token for this call.</param>
14+
/// <typeparam name="T">The type of the documents to return.</typeparam>
15+
/// <returns>Returns the similar documents.</returns>
16+
public async Task<SimilarDocumentsResult<T>> SearchSimilarDocumentsAsync<T>(
17+
SimilarDocumentsQuery query,
18+
CancellationToken cancellationToken = default)
19+
{
20+
var responseMessage = await _http
21+
.PostAsJsonAsync(
22+
$"indexes/{Uid}/similar",
23+
query,
24+
Constants.JsonSerializerOptionsRemoveNulls,
25+
cancellationToken: cancellationToken)
26+
.ConfigureAwait(false);
27+
28+
return await responseMessage.Content
29+
.ReadFromJsonAsync<SimilarDocumentsResult<T>>(cancellationToken: cancellationToken)
30+
.ConfigureAwait(false);
31+
}
32+
}
33+
}

src/Meilisearch/Meilisearch.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,8 @@
8686
<Compile Update="Index.Embedders.cs">
8787
<DependentUpon>Index.cs</DependentUpon>
8888
</Compile>
89+
<Compile Update="Index.SimilarDocuments.cs">
90+
<DependentUpon>Index.cs</DependentUpon>
91+
</Compile>
8992
</ItemGroup>
9093
</Project>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System;
2+
using System.Text.Json.Serialization;
3+
4+
namespace Meilisearch
5+
{
6+
/// <summary>
7+
/// Search query for similar documents.
8+
/// </summary>
9+
public class SimilarDocumentsQuery
10+
{
11+
/// <summary>
12+
/// Creates a new instance of the <see cref="SimilarDocumentsQuery"/> class.
13+
/// </summary>
14+
/// <param name="id"></param>
15+
public SimilarDocumentsQuery(string id)
16+
{
17+
if (string.IsNullOrEmpty(id))
18+
{
19+
throw new ArgumentNullException(nameof(id));
20+
}
21+
22+
Id = id;
23+
}
24+
25+
/// <summary>
26+
/// Gets the document id.
27+
/// </summary>
28+
[JsonPropertyName("id")]
29+
public string Id { get; }
30+
31+
/// <summary>
32+
/// Gets or sets the embedder.
33+
/// </summary>
34+
[JsonPropertyName("embedder")]
35+
public string Embedder { get; set; }
36+
37+
/// <summary>
38+
/// Gets or sets the attributes to retrieve.
39+
/// </summary>
40+
[JsonPropertyName("attributesToRetrieve")]
41+
public string[] AttributesToRetrieve { get; set; } = { "*" };
42+
43+
/// <summary>
44+
/// Gets or sets the offset.
45+
/// </summary>
46+
[JsonPropertyName("offset")]
47+
public int Offset { get; set; } = 0;
48+
49+
/// <summary>
50+
/// Gets or sets the limit.
51+
/// </summary>
52+
[JsonPropertyName("limit")]
53+
public int Limit { get; set; } = 20;
54+
55+
/// <summary>
56+
/// Gets or sets the filter.
57+
/// </summary>
58+
[JsonPropertyName("filter")]
59+
public string Filter { get; set; }
60+
61+
/// <summary>
62+
/// Gets or sets whether to show the ranking score.
63+
/// </summary>
64+
[JsonPropertyName("showRankingScore")]
65+
public bool ShowRankingScore { get; set; }
66+
67+
/// <summary>
68+
/// Gets or sets whether to show the ranking score details.
69+
/// </summary>
70+
[JsonPropertyName("showRankingScoreDetails")]
71+
public bool ShowRankingScoreDetails { get; set; }
72+
73+
/// <summary>
74+
/// Gets or sets the ranking score threshold.
75+
/// </summary>
76+
[JsonPropertyName("rankingScoreThreshold")]
77+
public int? RankingScoreThreshold { get; set; }
78+
79+
/// <summary>
80+
/// Gets or sets whether to retrieve the vectors.
81+
/// </summary>
82+
[JsonPropertyName("retrieveVectors")]
83+
public bool RetrieveVectors { get; set; }
84+
}
85+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using System.Collections.Generic;
2+
using System.Text.Json.Serialization;
3+
4+
namespace Meilisearch
5+
{
6+
/// <summary>
7+
/// Search result for similar documents.
8+
/// </summary>
9+
public class SimilarDocumentsResult<T>
10+
{
11+
/// <summary>
12+
/// Creates a new instance of the <see cref="SimilarDocumentsResult{T}"/> class.
13+
/// </summary>
14+
/// <param name="hits"></param>
15+
/// <param name="id"></param>
16+
/// <param name="processingTimeMs"></param>
17+
/// <param name="offset"></param>
18+
/// <param name="limit"></param>
19+
/// <param name="estimatedTotalHits"></param>
20+
public SimilarDocumentsResult(
21+
IReadOnlyCollection<T> hits,
22+
string id,
23+
int processingTimeMs,
24+
int offset,
25+
int limit,
26+
int estimatedTotalHits)
27+
{
28+
Hits = hits;
29+
Id = id;
30+
ProcessingTimeMs = processingTimeMs;
31+
Offset = offset;
32+
Limit = limit;
33+
EstimatedTotalHits = estimatedTotalHits;
34+
}
35+
36+
/// <summary>
37+
/// Gets the hits.
38+
/// </summary>
39+
[JsonPropertyName("hits")]
40+
public IReadOnlyCollection<T> Hits { get; }
41+
42+
/// <summary>
43+
/// Gets or sets the id.
44+
/// </summary>
45+
[JsonPropertyName("id")]
46+
public string Id { get; }
47+
48+
/// <summary>
49+
/// Gets or sets the processing time in milliseconds.
50+
/// </summary>
51+
[JsonPropertyName("processingTimeMs")]
52+
public int ProcessingTimeMs { get; }
53+
54+
/// <summary>
55+
/// Gets or sets the offset.
56+
/// </summary>
57+
[JsonPropertyName("offset")]
58+
public int Offset { get; }
59+
60+
/// <summary>
61+
/// Gets or sets the limit.
62+
/// </summary>
63+
[JsonPropertyName("limit")]
64+
public int Limit { get; }
65+
66+
/// <summary>
67+
/// Gets or sets the estimated total hits.
68+
/// </summary>
69+
[JsonPropertyName("estimatedTotalHits")]
70+
public int EstimatedTotalHits { get; }
71+
}
72+
}

tests/Meilisearch.Tests/SearchTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,5 +577,23 @@ public async Task CustomSearchWithVector()
577577
Assert.Equal("522681", movies.Hits.First().Id);
578578
Assert.Equal("Escape Room", movies.Hits.First().Title);
579579
}
580+
581+
[Fact]
582+
public async Task CustomSearchWithSimilarDocuments()
583+
{
584+
var query = new SimilarDocumentsQuery("143")
585+
{
586+
Embedder = "manual"
587+
};
588+
589+
var movies = await _indexForVectorSearch.SearchSimilarDocumentsAsync<VectorMovie>(query);
590+
591+
Assert.Collection(movies.Hits,
592+
m => Assert.Equal("Escape Room", m.Title),
593+
m => Assert.Equal("Captain Marvel", m.Title),
594+
m => Assert.Equal("How to Train Your Dragon: The Hidden World", m.Title),
595+
m => Assert.Equal("Shazam!", m.Title)
596+
);
597+
}
580598
}
581599
}

0 commit comments

Comments
 (0)