diff --git a/clients/algoliasearch-client-python/algoliasearch/http/base_config.py b/clients/algoliasearch-client-python/algoliasearch/http/base_config.py index 82eb4bc09c6..d0f2a0a8f87 100644 --- a/clients/algoliasearch-client-python/algoliasearch/http/base_config.py +++ b/clients/algoliasearch-client-python/algoliasearch/http/base_config.py @@ -24,7 +24,7 @@ def __init__(self, app_id: Optional[str] = None, api_key: Optional[str] = None): self.connect_timeout = 2000 self.wait_task_time_before_retry: Optional[int] = None - self.headers: Optional[Dict[str, str]] = None + self.headers: Dict[str, str] = {} self.proxies: Optional[Dict[str, str]] = None self.hosts: Optional[HostsCollection] = None @@ -33,13 +33,9 @@ def __init__(self, app_id: Optional[str] = None, api_key: Optional[str] = None): def set_client_api_key(self, api_key: str) -> None: """Sets a new API key to authenticate requests.""" self.api_key = api_key - if self.headers is None: - self.headers = {} self.headers["x-algolia-api-key"] = api_key def add_user_agent(self, segment: str, version: Optional[str] = None) -> None: """adds a segment to the default user agent, and update the headers sent with each requests as well""" self._user_agent = self._user_agent.add(segment, version) - - if self.headers is not None: - self.headers["user-agent"] = self._user_agent.get() + self.headers["user-agent"] = self._user_agent.get() diff --git a/clients/algoliasearch-client-python/algoliasearch/http/request_options.py b/clients/algoliasearch-client-python/algoliasearch/http/request_options.py index 7d87610f0bd..5039c2dca93 100644 --- a/clients/algoliasearch-client-python/algoliasearch/http/request_options.py +++ b/clients/algoliasearch-client-python/algoliasearch/http/request_options.py @@ -69,7 +69,7 @@ def merge( query_parameters = {} if headers is None: headers = {} - headers.update(self._config.headers or {}) + headers.update(self._config.headers) request_options = { "headers": headers, diff --git a/templates/csharp/guides/search/deleteMultipleIndices.mustache b/templates/csharp/guides/search/deleteMultipleIndices.mustache index 8e844887bc1..374ac8a3365 100644 --- a/templates/csharp/guides/search/deleteMultipleIndices.mustache +++ b/templates/csharp/guides/search/deleteMultipleIndices.mustache @@ -13,35 +13,31 @@ class DeleteMultipleIndices { { // You need an API key with `deleteIndex` - try { - {{> snippets/init}} - - // List all indices - var indices = {{#dynamicSnippet}}listIndicesSimple{{/dynamicSnippet}}; - - // Primary indices don't have a `primary` key - var primaryIndices = indices.Items.Where(item => item.Primary == null).ToList(); - var replicaIndices = indices.Items.Where(item => item.Primary != null).ToList(); - - // Delete primary indices first - if (primaryIndices.Count > 0) - { - var requests = primaryIndices - .Select(index => new MultipleBatchRequest(Search.Models.Search.Action.Delete, index.Name)).ToList(); - {{#dynamicSnippet}}deleteMultipleIndicesPrimary{{/dynamicSnippet}}; - Console.WriteLine("Deleted primary indices."); - } - - // Now, delete replica indices - if (replicaIndices.Count > 0) - { - var requests = replicaIndices - .Select(index => new MultipleBatchRequest(Search.Models.Search.Action.Delete, index.Name)).ToList(); - {{#dynamicSnippet}}deleteMultipleIndicesReplica{{/dynamicSnippet}}; - Console.WriteLine("Deleted replica indices."); - } - } catch (Exception e) { - Console.WriteLine(e.Message); + {{> snippets/init}} + + // List all indices + var indices = {{#dynamicSnippet}}listIndicesSimple{{/dynamicSnippet}}; + + // Primary indices don't have a `primary` key + var primaryIndices = indices.Items.Where(item => item.Primary == null).ToList(); + var replicaIndices = indices.Items.Where(item => item.Primary != null).ToList(); + + // Delete primary indices first + if (primaryIndices.Count > 0) + { + var requests = primaryIndices + .Select(index => new MultipleBatchRequest(Search.Models.Search.Action.Delete, index.Name)).ToList(); + {{#dynamicSnippet}}deleteMultipleIndicesPrimary{{/dynamicSnippet}}; + Console.WriteLine("Deleted primary indices."); + } + + // Now, delete replica indices + if (replicaIndices.Count > 0) + { + var requests = replicaIndices + .Select(index => new MultipleBatchRequest(Search.Models.Search.Action.Delete, index.Name)).ToList(); + {{#dynamicSnippet}}deleteMultipleIndicesReplica{{/dynamicSnippet}}; + Console.WriteLine("Deleted replica indices."); } } } \ No newline at end of file diff --git a/templates/csharp/guides/search/globalAlgoliaUserID.mustache b/templates/csharp/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..8ad3bd1337d --- /dev/null +++ b/templates/csharp/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,22 @@ +namespace Algolia; + +using System; +using System.Text.Json; +using System.Net.Http; +using System.Collections.Generic; + +{{> snippets/import}} + +class GlobalAlgoliaUserID +{ + async Task Main(string[] args) + { + var client = new SearchClient( + new SearchConfig("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY") + { + DefaultHeaders = new Dictionary { { "X-Algolia-UserToken", "test-user-123" } } + } + ); + Console.WriteLine(client); + } +} diff --git a/templates/csharp/guides/search/mcmSearchWithout.mustache b/templates/csharp/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..f6e7fd98ddf --- /dev/null +++ b/templates/csharp/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,38 @@ +namespace Algolia; + +using System; +using System.Text.Json; +using System.Net.Http; +using System.Collections.Generic; + +{{> snippets/import}} + +class McmSearchWithout { + + private static string GetAppIdFor(string user) { + return ""; // Implement your own logic here + } + + private static string GetIndexingApiKeyFor(string user) { + return ""; // Implement your own logic here + } + + async Task Main(string[] args) + { + + // Fetch from your own data storage and with your own code + // the associated application ID and API key for this user + var appId = GetAppIdFor("user42"); + var apiKey = GetIndexingApiKeyFor("user42"); + + var client = new SearchClient(new SearchConfig(appId, apiKey)); + var searchParams = new SearchParams(new SearchParamsObject + { + Query = "", + FacetFilters = new FacetFilters([new FacetFilters("user:user42"), new FacetFilters("user:public")]) + } + ); + + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; + } +} \ No newline at end of file diff --git a/templates/csharp/guides/search/saveImageClassifications.mustache b/templates/csharp/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..dfd301c8171 --- /dev/null +++ b/templates/csharp/guides/search/saveImageClassifications.mustache @@ -0,0 +1,54 @@ +namespace Algolia; + +using System; +using System.Text.Json; +using System.Net.Http; +using System.Collections.Generic; + +{{> snippets/import}} + +class SaveImageClassifications { + + class Image + { + public required string ImageUrl { get; set; } + public required string ObjectId { get; set; } + public required List> Objects { get; set; } + } + + // Retrieve labels + async Task GetImageLabels(string imageURL, string objectID, float scoreLimit) + { + // Implement your image classification logic here + return await Task.Run(() => new Image + { + ImageUrl = "", + ObjectId = "", + Objects = [] + }); + } + + async Task Main(string[] args) + { + + try { + // API key ACL should include editSettings / addObject + {{> snippets/init}} + + var hits = await client.BrowseObjectsAsync( + "", + new BrowseParamsObject() + ); + + var records = hits + .Select(hit => GetImageLabels(hit.ImageUrl, hit.ObjectId, 0.5f)) + .Select(src => src.Result) + .ToList(); + + // Update records with image classifications + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}}; + } catch (Exception e) { + Console.WriteLine(e.Message); + } + } +} diff --git a/templates/csharp/guides/search/saveImageClassificationsAndSettings.mustache b/templates/csharp/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..5d5f2e4612c --- /dev/null +++ b/templates/csharp/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,84 @@ +namespace Algolia; + +using System; +using System.Text.Json; +using System.Net.Http; +using System.Collections.Generic; + +{{> snippets/import}} + +class SaveImageClassificationsAndSettings { + + class Image + { + public required string ImageUrl { get; set; } + public required string ObjectId { get; set; } + public required List> Objects { get; set; } + } + + // Retrieve labels + async Task GetImageLabels(string imageURL, string objectID, float scoreLimit) + { + // Implement your image classification logic here + return await Task.Run(() => new Image + { + ImageUrl = "", + ObjectId = "", + Objects = [] + }); + } + + async Task Main(string[] args) + { + + try { + // API key ACL should include editSettings / addObject + {{> snippets/init}} + + var hits = await client.BrowseObjectsAsync( + "", + new BrowseParamsObject() + ); + + var images = hits.ToList(); + var records = images + .Select(hit => GetImageLabels(hit.ImageUrl, hit.ObjectId, 0.5f)) + .Select(src => src.Result) + .ToList(); + + // Update records with image classifications + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}}; + + List facets = []; + List attributes = []; + + foreach (var image in images) + { + foreach (var obj in image.Objects) + { + foreach (var key in obj.Keys) + { + if (obj[key] is IEnumerable) + { + facets.Add($"searchable(objects.{key}.label)"); + facets.Add($"searchable(objects.{key}.score)"); + attributes.Add($"objects.{key}.label"); + } + } + } + } + + var currentSettings = {{#dynamicSnippet}}getSettings{{/dynamicSnippet}}; + + var settings = new IndexSettings + { + SearchableAttributes = currentSettings.SearchableAttributes.Concat(attributes).ToList(), + AttributesForFaceting = currentSettings.AttributesForFaceting.Concat(facets).ToList() + }; + + {{#dynamicSnippet}}setSettings{{/dynamicSnippet}}; + } catch (Exception e) { + Console.WriteLine(e.Message); + } + } +} diff --git a/templates/csharp/guides/search/saveObjectsChunks.mustache b/templates/csharp/guides/search/saveObjectsChunks.mustache index 73ea2af99d4..bcf5ba1f451 100644 --- a/templates/csharp/guides/search/saveObjectsChunks.mustache +++ b/templates/csharp/guides/search/saveObjectsChunks.mustache @@ -12,20 +12,20 @@ class SaveObjectsChunks { async Task Main(string[] args) { - try { - {{> snippets/init}} - var jsonContent = await File.ReadAllTextAsync("actors.json"); - var records = JsonSerializer.Deserialize>>(jsonContent); + {{> snippets/init}} + var jsonContent = await File.ReadAllTextAsync("actors.json"); + var records = JsonSerializer.Deserialize>>(jsonContent); - const int chunkSize = 10000; + const int chunkSize = 10000; - for (var beginIndex = 0; beginIndex < records?.Count; beginIndex += chunkSize) - { + for (var beginIndex = 0; beginIndex < records?.Count; beginIndex += chunkSize) + { + try { var chunk = records.Slice(beginIndex, Math.Min(beginIndex + chunkSize, records.Count)); {{#dynamicSnippet}}saveObjectsChunks{{/dynamicSnippet}}; + } catch (Exception e) { + Console.WriteLine(e.Message); } - } catch (Exception e) { - Console.WriteLine(e.Message); } } } diff --git a/templates/csharp/guides/search/saveObjectsModified.mustache b/templates/csharp/guides/search/saveObjectsModified.mustache index aebd872eaf5..0bc5c95f1ab 100644 --- a/templates/csharp/guides/search/saveObjectsModified.mustache +++ b/templates/csharp/guides/search/saveObjectsModified.mustache @@ -12,31 +12,27 @@ class SaveObjectsModified { async Task Main(string[] args) { - try { - {{> snippets/init}} + {{> snippets/init}} - var jsonContent = await File.ReadAllTextAsync("products.json"); - var products = JsonSerializer.Deserialize>>(jsonContent); + var jsonContent = await File.ReadAllTextAsync("products.json"); + var products = JsonSerializer.Deserialize>>(jsonContent); - var records = products?.Select(product => + var records = products?.Select(product => + { + var reference = product.GetValueOrDefault("product_reference", "") as string; + var suffixes = new List(); + + for (var i = reference!.Length; i > 1; i--) + { + suffixes.Add(reference[i..]); + } + + return new Dictionary(product) { - var reference = product.GetValueOrDefault("product_reference", "") as string; - var suffixes = new List(); - - for (var i = reference!.Length; i > 1; i--) - { - suffixes.Add(reference[i..]); - } - - return new Dictionary(product) - { - ["suffixes"] = suffixes - }; - }).ToList(); - - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + ["suffixes"] = suffixes + }; + }).ToList(); + + {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/saveObjectsPublicUser.mustache b/templates/csharp/guides/search/saveObjectsPublicUser.mustache index b376b209025..b971ee396df 100644 --- a/templates/csharp/guides/search/saveObjectsPublicUser.mustache +++ b/templates/csharp/guides/search/saveObjectsPublicUser.mustache @@ -14,11 +14,7 @@ class SaveObjectsPublicUser { async Task Main(string[] args) { - try { - {{> snippets/init}} - {{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{> snippets/init}} + {{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}}; } } \ No newline at end of file diff --git a/templates/csharp/guides/search/savePopularRecords.mustache b/templates/csharp/guides/search/savePopularRecords.mustache index 99a6a001505..53055dfd05d 100644 --- a/templates/csharp/guides/search/savePopularRecords.mustache +++ b/templates/csharp/guides/search/savePopularRecords.mustache @@ -7,34 +7,30 @@ using System.Collections.Generic; {{> snippets/import}} -class SavePopularRecords { +class SavePopularRecords +{ + + class Record + { + public int NbFollowers { get; set; } + public required string TwitterHandle { get; set; } + public bool IsPopular { get; set; } + } async Task Main(string[] args) { - try { - {{> snippets/init}} - var records = new List>(); + {{> snippets/init}} - var hits = await client.BrowseObjectsAsync("", new BrowseParamsObject()); + var hits = await client.BrowseObjectsAsync("", new BrowseParamsObject()); - foreach (var hit in hits) + var records = hits.Select(hit => new Record { - var props = hit.AdditionalProperties ?? new Dictionary(); - var nbFollowers = props["nbFollowers"] as int? ?? 0; - records.Add( - new Dictionary - { - ["twitterHandle"] = props["twitterHandle"], - ["nbFollowers"] = nbFollowers, - ["isPopular"] = nbFollowers >= 1_000_000 - } - ); - } - - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + TwitterHandle = hit.TwitterHandle, + NbFollowers = hit.NbFollowers, + IsPopular = hit.NbFollowers >= 1_000_000 + }).ToList(); + + {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/searchFuturePublishedBooks.mustache b/templates/csharp/guides/search/searchFuturePublishedBooks.mustache index 090c91ef8e2..fa24dd5bde3 100644 --- a/templates/csharp/guides/search/searchFuturePublishedBooks.mustache +++ b/templates/csharp/guides/search/searchFuturePublishedBooks.mustache @@ -12,19 +12,15 @@ class SearchFuturePublishedBooks { async Task Main(string[] args) { - try { - {{> snippets/init}} - var dateTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); - var searchParams = new SearchParams(new SearchParamsObject - { - Query = "", - Filters = $"date_timestamp > {dateTimestamp}" - } - ); + {{> snippets/init}} + var dateTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + var searchParams = new SearchParams(new SearchParamsObject + { + Query = "", + Filters = $"date_timestamp > {dateTimestamp}" + } + ); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/searchInReplicaIndex.mustache b/templates/csharp/guides/search/searchInReplicaIndex.mustache index ce5dbe77ca7..e5c5b2dacfc 100644 --- a/templates/csharp/guides/search/searchInReplicaIndex.mustache +++ b/templates/csharp/guides/search/searchInReplicaIndex.mustache @@ -12,22 +12,18 @@ class SearchInReplicaIndex { async Task Main(string[] args) { - try { - {{> snippets/init}} + {{> snippets/init}} - var query = "query"; + var query = "query"; - // 1. Change the sort dynamically based on the UI events - var sortByPrice = false; + // 1. Change the sort dynamically based on the UI events + var sortByPrice = false; - // 2. Get the index name based on sortByPrice - var indexName = sortByPrice ? "products_price_desc" : "products"; + // 2. Get the index name based on sortByPrice + var indexName = sortByPrice ? "products_price_desc" : "products"; - // 3. Search on dynamic index name (primary or replica) - {{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + // 3. Search on dynamic index name (primary or replica) + {{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/searchRecentlyPublishedBooks.mustache b/templates/csharp/guides/search/searchRecentlyPublishedBooks.mustache index 4eb03d793db..aec6ae1ef06 100644 --- a/templates/csharp/guides/search/searchRecentlyPublishedBooks.mustache +++ b/templates/csharp/guides/search/searchRecentlyPublishedBooks.mustache @@ -12,21 +12,17 @@ class SearchRecentlyPublishedBooks { async Task Main(string[] args) { - try { - {{> snippets/init}} - var date = DateTime.UtcNow.AddYears(-1); - var sTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - var unixTime = (long)(date - sTime).TotalSeconds; - var searchParams = new SearchParams(new SearchParamsObject - { - Query = "", - Filters = $"date_timestamp > {unixTime}" - } - ); + {{> snippets/init}} + var date = DateTime.UtcNow.AddYears(-1); + var sTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + var unixTime = (long)(date - sTime).TotalSeconds; + var searchParams = new SearchParams(new SearchParamsObject + { + Query = "", + Filters = $"date_timestamp > {unixTime}" + } + ); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/searchWithAnalyticsAndHeader.mustache b/templates/csharp/guides/search/searchWithAnalyticsAndHeader.mustache index e2c4764a023..5dae08a5027 100644 --- a/templates/csharp/guides/search/searchWithAnalyticsAndHeader.mustache +++ b/templates/csharp/guides/search/searchWithAnalyticsAndHeader.mustache @@ -12,22 +12,18 @@ class SearchWithAnalyticsAndHeader { async Task Main(string[] args) { - try { - {{> snippets/init}} - - /* - '94.228.178.246' should be replaced with your user's IP address. - Depending on your stack there are multiple ways to get this information. - */ - var ip = "94.228.178.246"; - var query = "query"; - - var searchParams = new SearchParams(new SearchParamsObject { Query = query, Analytics = true }); - - {{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{> snippets/init}} + + /* + '94.228.178.246' should be replaced with your user's IP address. + Depending on your stack there are multiple ways to get this information. + */ + var ip = "94.228.178.246"; + var query = "query"; + + var searchParams = new SearchParams(new SearchParamsObject { Query = query, Analytics = true }); + + {{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/searchWithGAToken.mustache b/templates/csharp/guides/search/searchWithGAToken.mustache index 5d7761f1297..0e2c05e05e8 100644 --- a/templates/csharp/guides/search/searchWithGAToken.mustache +++ b/templates/csharp/guides/search/searchWithGAToken.mustache @@ -16,25 +16,21 @@ class SearchWithGAToken { async Task Main(string[] args) { - try { - {{> snippets/init}} - var userToken = GetGoogleAnalyticsUserIdFromBrowserCookie("_ga"); - var searchParams = new SearchParams( - new SearchParamsObject - { - Query = "", - UserToken = userToken - } - ); - - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; - - string? loggedInUser = null; - searchParams.AsSearchParamsObject().UserToken = loggedInUser ?? userToken; - - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{> snippets/init}} + var userToken = GetGoogleAnalyticsUserIdFromBrowserCookie("_ga"); + var searchParams = new SearchParams( + new SearchParamsObject + { + Query = "", + UserToken = userToken + } + ); + + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; + + string? loggedInUser = null; + searchParams.AsSearchParamsObject().UserToken = loggedInUser ?? userToken; + + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; } } \ No newline at end of file diff --git a/templates/csharp/guides/search/searchWithLogicalOr.mustache b/templates/csharp/guides/search/searchWithLogicalOr.mustache index c5ad9d22d70..4d1054366cb 100644 --- a/templates/csharp/guides/search/searchWithLogicalOr.mustache +++ b/templates/csharp/guides/search/searchWithLogicalOr.mustache @@ -12,23 +12,19 @@ class SearchWithLogicalOr { async Task Main(string[] args) { - try { - {{> snippets/init}} + {{> snippets/init}} - var query = "the query"; + var query = "the query"; - var optionalWords = new OptionalWords(["the", "query"]); + var optionalWords = new OptionalWords(["the", "query"]); - var searchParams = new SearchParams(new SearchParamsObject - { - Query = query, - OptionalWords = optionalWords - }); + var searchParams = new SearchParams(new SearchParamsObject + { + Query = query, + OptionalWords = optionalWords + }); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/searchWithOptionalFilters.mustache b/templates/csharp/guides/search/searchWithOptionalFilters.mustache index 952a659fd90..3d916ed375f 100644 --- a/templates/csharp/guides/search/searchWithOptionalFilters.mustache +++ b/templates/csharp/guides/search/searchWithOptionalFilters.mustache @@ -19,18 +19,14 @@ class SearchWithOptionalFilters { async Task Main(string[] args) { - try { - {{> snippets/init}} - var optionalFilters = ReduceLabelsToFilters(labels); - var searchParams = new SearchParams(new SearchParamsObject - { - Query = "", - OptionalFilters = optionalFilters - }); - - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{> snippets/init}} + var optionalFilters = ReduceLabelsToFilters(labels); + var searchParams = new SearchParams(new SearchParamsObject + { + Query = "", + OptionalFilters = optionalFilters + }); + + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/searchWithRuleContextBuyer.mustache b/templates/csharp/guides/search/searchWithRuleContextBuyer.mustache index 41edf559922..409c4e76b88 100644 --- a/templates/csharp/guides/search/searchWithRuleContextBuyer.mustache +++ b/templates/csharp/guides/search/searchWithRuleContextBuyer.mustache @@ -16,19 +16,15 @@ class SearchWithRuleContextBuyer { async Task Main(string[] args) { - try { - {{> snippets/init}} - // get the buyer account information - var buyer = GetBuyerAccountId(); - var searchParams = new SearchParams(new SearchParamsObject - { - Query = "", - RuleContexts = [buyer] - }); + {{> snippets/init}} + // get the buyer account information + var buyer = GetBuyerAccountId(); + var searchParams = new SearchParams(new SearchParamsObject + { + Query = "", + RuleContexts = [buyer] + }); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/searchWithRuleContexts.mustache b/templates/csharp/guides/search/searchWithRuleContexts.mustache index b73001b4ea3..760b24c8e59 100644 --- a/templates/csharp/guides/search/searchWithRuleContexts.mustache +++ b/templates/csharp/guides/search/searchWithRuleContexts.mustache @@ -16,18 +16,14 @@ class SearchWithRuleContexts { async Task Main(string[] args) { - try { - {{> snippets/init}} - var platformTag = GetPlatformTag(); - var searchParams = new SearchParams(new SearchParamsObject - { - Query = "", - RuleContexts = [platformTag] - }); + {{> snippets/init}} + var platformTag = GetPlatformTag(); + var searchParams = new SearchParams(new SearchParamsObject + { + Query = "", + RuleContexts = [platformTag] + }); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; } } diff --git a/templates/csharp/guides/search/setHeaderUserIDThenSaveObjects.mustache b/templates/csharp/guides/search/setHeaderUserIDThenSaveObjects.mustache index 013dadb4181..2d0977cb11f 100644 --- a/templates/csharp/guides/search/setHeaderUserIDThenSaveObjects.mustache +++ b/templates/csharp/guides/search/setHeaderUserIDThenSaveObjects.mustache @@ -14,14 +14,14 @@ class SetHeaderUserIDThenSaveObjects { async Task Main(string[] args) { - try { - {{> snippets/init}} - foreach (var playlist in playlists) { + {{> snippets/init}} + foreach (var playlist in playlists) { + try { var playlistUserID = playlist.GetValueOrDefault("userID", "") as string; {{#dynamicSnippet}}saveObjectsPlaylistsWithRequestOptions{{/dynamicSnippet}}; + } catch (Exception e) { + Console.WriteLine(e.Message); } - } catch (Exception e) { - Console.WriteLine(e.Message); } } } \ No newline at end of file diff --git a/templates/csharp/guides/search/useConditionlessRule.mustache b/templates/csharp/guides/search/useConditionlessRule.mustache index 820d058e019..239a8497abe 100644 --- a/templates/csharp/guides/search/useConditionlessRule.mustache +++ b/templates/csharp/guides/search/useConditionlessRule.mustache @@ -12,22 +12,18 @@ class UseConditionlessRule { async Task Main(string[] args) { - try { - {{> snippets/init}} - - var objectID = "a-rule-id"; - - var rule = new Rule - { - ObjectID = objectID, - Consequence = new Consequence(/* Set relevant consequence */), - // Set validity (optional) - Validity = [new TimeRange { From = 1688774400L, Until = 1738972800L }] - }; - - {{#dynamicSnippet}}saveRule{{/dynamicSnippet}}; - } catch (Exception e) { - Console.WriteLine(e.Message); - } + {{> snippets/init}} + + var objectID = "a-rule-id"; + + var rule = new Rule + { + ObjectID = objectID, + Consequence = new Consequence(/* Set relevant consequence */), + // Set validity (optional) + Validity = [new TimeRange { From = 1688774400L, Until = 1738972800L }] + }; + + {{#dynamicSnippet}}saveRule{{/dynamicSnippet}}; } } diff --git a/templates/dart/guides/search/globalAlgoliaUserID.mustache b/templates/dart/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..030b3f4342d --- /dev/null +++ b/templates/dart/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,13 @@ +{{> snippets/import}} + +void globalAlgoliaUserID() async { + final client = SearchClient( + appId: 'ALGOLIA_APPLICATION_ID', + apiKey: 'ALGOLIA_API_KEY', + options: ClientOptions( + headers: { + 'X-Algolia-User-ID': 'test-user-123', + }, + )); + print(client.options.headers); +} diff --git a/templates/dart/guides/search/mcmSearchWithout.mustache b/templates/dart/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..a18797ce6ab --- /dev/null +++ b/templates/dart/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,24 @@ +{{> snippets/import}} + +String getAppIDFor(String _) { + return ""; // Implement your own logic here +} + +String getIndexingApiKeyFor(String _) { + return ""; // Implement your own logic here +} + +void mcmSearchWithout() async { + // Fetch from your own data storage and with your own code + // the associated application ID and API key for this user + final appId = getAppIDFor("user42"); + final apiKey = getIndexingApiKeyFor("user42"); + + final client = SearchClient(appId: appId, apiKey: apiKey); + final searchParams = SearchParamsObject( + query: "", + facetFilters: ["user:user42", "user:public"] + ); + + await {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; +} \ No newline at end of file diff --git a/templates/dart/guides/search/saveImageClassifications.mustache b/templates/dart/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..b1abc27311f --- /dev/null +++ b/templates/dart/guides/search/saveImageClassifications.mustache @@ -0,0 +1,47 @@ +{{> snippets/import}} + +final class Image { + final String imageUrl; + final String objectID; + List> objects; + + Image(String imageUrl, String objectID, List> objects) + : + this.imageUrl = imageUrl, + this.objectID = objectID, + this.objects = objects; +} + +Future> getImageLabels(String imageURL, String objectID, double scoreLimit) async { + // Implement your image classification logic here + return {}; +} + +void saveImageClassifications() async { + // API key ACL should include editSettings / addObject + {{> snippets/init}} + + final List> records = []; + + BrowseResponse? browseResponse; + do { + final browseParams = BrowseParamsObject(hitsPerPage: 1000, cursor: browseResponse?.cursor); + browseResponse = await client.browse(indexName: "", browseParams: browseParams); + for (final hit in browseResponse.hits) { + final props = hit.toJson(); + final imageWithLabels = await getImageLabels(props["imageUrl"], hit.objectID, 0.5); + records.add(imageWithLabels); + } + } while (browseResponse.cursor != null); + + final batchParams = BatchWriteParams( + requests: records.map((record) => + BatchRequest( + action: Action.partialUpdateObject, + body: record, + )) + .toList()); + + // Update records with image classifications + await {{#dynamicSnippet}}batchChunks{{/dynamicSnippet}}; +} diff --git a/templates/dart/guides/search/saveImageClassificationsAndSettings.mustache b/templates/dart/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..6b1b04249c7 --- /dev/null +++ b/templates/dart/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,71 @@ +{{> snippets/import}} + +final class Image { + final String imageUrl; + final String objectID; + List> objects; + + Image(String imageUrl, String objectID, List> objects) + : + this.imageUrl = imageUrl, + this.objectID = objectID, + this.objects = objects; +} + +Future> getImageLabels(String imageURL, String objectID, double scoreLimit) async { + // Implement your image classification logic here + return {}; +} + +void saveImageClassifications() async { + // API key ACL should include editSettings / addObject + {{> snippets/init}} + + final List> records = []; + + BrowseResponse? browseResponse; + do { + final browseParams = BrowseParamsObject(hitsPerPage: 1000, cursor: browseResponse?.cursor); + browseResponse = await client.browse(indexName: "", browseParams: browseParams); + for (final hit in browseResponse.hits) { + final props = hit.toJson(); + final imageWithLabels = await getImageLabels(props["imageUrl"], hit.objectID, 0.5); + records.add(imageWithLabels); + } + } while (browseResponse.cursor != null); + + final batchParams = BatchWriteParams( + requests: records.map((record) => + BatchRequest( + action: Action.partialUpdateObject, + body: record, + )) + .toList()); + + // Update records with image classifications + await {{#dynamicSnippet}}batchChunks{{/dynamicSnippet}}; + + List facets = []; + List attributes = []; + + records.forEach((record) { + record["objects"].forEach((object) { + object.forEach((key, values) { + if (values is Iterable) { + facets.add("searchable(objects.${key}.label)"); + facets.add("searchable(objects.${key}.score)"); + attributes.add("objects.${key}.label"); + } + }); + }); + }); + + final currentSettings = await {{#dynamicSnippet}}getSettings{{/dynamicSnippet}}; + + final settings = IndexSettings( + searchableAttributes: (currentSettings.searchableAttributes ?? []) + attributes, + attributesForFaceting: (currentSettings.attributesForFaceting ?? []) + facets, + ); + + await {{#dynamicSnippet}}setSettings{{/dynamicSnippet}}; +} diff --git a/templates/go/guides/search/globalAlgoliaUserID.mustache b/templates/go/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..ba0b0dc2861 --- /dev/null +++ b/templates/go/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,18 @@ +package main + +import ( + "encoding/json" + "fmt" + "net/http" +) + +{{> snippets/import}} + +func globalAlgoliaUserID() { + client, err := search.NewClient("YourApplicationID", "YourAdminAPIKey") + if err != nil { + fmt.Println(err) + } + + client.AddDefaultHeader("X-Algolia-UserToken", "test-user-123") +} diff --git a/templates/go/guides/search/mcmSearchWithout.mustache b/templates/go/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..be1b99605e9 --- /dev/null +++ b/templates/go/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,57 @@ +package main + +import ( + "encoding/json" + "fmt" + "net/http" +) + +{{> snippets/import}} + +func mcmSearchWithout() { + getAppIDFor := func(_ string) (string, error) { + return "", nil // Implement your logic here + } + + getIndexingApiKeyFor := func(_ string) (string, error) { + return "", nil // Implement your logic here + } + + // Fetch from your own data storage and with your own code + // the associated application ID and API key for this user + appID, err := getAppIDFor("user42") + if err != nil { + fmt.Println(err) + return + } + + apiKey, err := getIndexingApiKeyFor("user42") + if err != nil { + fmt.Println(err) + return + } + + client, err := search.NewClient(appID, apiKey) + if err != nil { + fmt.Println(err) + return + } + + searchParams := search.SearchParamsObjectAsSearchParams( + search.NewSearchParamsObject(). + SetQuery(""). + SetFacetFilters( + search.ArrayOfFacetFiltersAsFacetFilters( + []search.FacetFilters{ + *search.StringAsFacetFilters("user:user42"), + *search.StringAsFacetFilters("user:public"), + }, + ), + ), + ) + + _, err = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + if err != nil { + panic(err) + } +} \ No newline at end of file diff --git a/templates/go/guides/search/saveImageClassifications.mustache b/templates/go/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..32d1df0b72a --- /dev/null +++ b/templates/go/guides/search/saveImageClassifications.mustache @@ -0,0 +1,63 @@ +package main + +import ( + "fmt" + "net/http" +) + +{{> snippets/import}} + +func saveImageClassifications() { + type Image struct { + ImageURL string `json:"imageURL"` + ObjectID string `json:"objectID"` + Objects []map[string]interface{} `json:"objects"` + } + + getImageLabels := func(imageURL, objectID string, scoreLimit float64) Image { + // Implement your image classification logic here + return Image{ + ImageURL: imageURL, + ObjectID: objectID, + Objects: []map[string]interface{}{}, + } + } + + {{> snippets/init}} + + images := []Image{} + + err = client.BrowseObjects("", search.BrowseParamsObject{}, search.WithAggregator(func(res any, err error) { + if err != nil { + panic(err) + } + + browseRes, ok := res.(search.BrowseResponse) + if !ok { + panic("Invalid response") + } + + for _, hit := range browseRes.Hits { + props := hit.AdditionalProperties + imageURL, _ := props["imageURL"].(string) + images = append(images, getImageLabels(imageURL, hit.GetObjectID(), 0.5)) + } + })) + if err != nil { + panic(err) + } + + records := make([]map[string]any, len(images)) + for i, img := range images { + records[i] = map[string]any{ + "imageURL": img.ImageURL, + "objectID": img.ObjectID, + "objects": img.Objects, + } + } + + _, err = {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} + if err != nil { + panic(err) + } +} \ No newline at end of file diff --git a/templates/go/guides/search/saveImageClassificationsAndSettings.mustache b/templates/go/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..e49ec51dde5 --- /dev/null +++ b/templates/go/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,94 @@ +package main + +import ( + "fmt" + "net/http" +) + +{{> snippets/import}} + +func saveImageClassificationsAndSettings() { + type Image struct { + ImageURL string `json:"imageURL"` + ObjectID string `json:"objectID"` + Objects []map[string]interface{} `json:"objects"` + } + + getImageLabels := func(imageURL, objectID string, scoreLimit float64) Image { + // Implement your image classification logic here + return Image{ + ImageURL: imageURL, + ObjectID: objectID, + Objects: []map[string]interface{}{}, + } + } + + {{> snippets/init}} + + images := []Image{} + + err = client.BrowseObjects("", search.BrowseParamsObject{}, search.WithAggregator(func(res any, err error) { + if err != nil { + panic(err) + } + + browseRes, ok := res.(search.BrowseResponse) + if !ok { + panic("Invalid response") + } + + for _, hit := range browseRes.Hits { + props := hit.AdditionalProperties + imageURL, _ := props["imageURL"].(string) + images = append(images, getImageLabels(imageURL, hit.GetObjectID(), 0.5)) + } + })) + if err != nil { + panic(err) + } + + records := make([]map[string]any, len(images)) + for i, img := range images { + records[i] = map[string]any{ + "imageURL": img.ImageURL, + "objectID": img.ObjectID, + "objects": img.Objects, + } + } + + _, err = {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} + if err != nil { + panic(err) + } + + facets := []string{} + attributes := []string{} + + for _, record := range images { + for _, obj := range record.Objects { + for key, values := range obj { + if _, ok := values.([]any); ok { + facets = append(facets, + fmt.Sprintf("searchable(objects.%s.label)", key), + fmt.Sprintf("searchable(objects.%s.score)", key), + ) + attributes = append(attributes, fmt.Sprintf("objects.%s.label)", key)) + } + } + } + } + + currentSettings, err := {{#dynamicSnippet}}getSettings{{/dynamicSnippet}} + if err != nil { + panic(err) + } + + settings := search.NewIndexSettings(). + SetSearchableAttributes(append(currentSettings.SearchableAttributes, attributes...)). + SetAttributesForFaceting(append(currentSettings.AttributesForFaceting, facets...)) + + _, err = {{#dynamicSnippet}}setSettings{{/dynamicSnippet}} + if err != nil { + panic(err) + } +} \ No newline at end of file diff --git a/templates/java/guides/search/globalAlgoliaUserID.mustache b/templates/java/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..0153489068e --- /dev/null +++ b/templates/java/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,15 @@ +package com.algolia; + +{{> snippets/import}} + +public class globalAlgoliaUserID { + + public static void main(String[] args) throws Exception { + SearchClient client = new SearchClient( + "ALGOLIA_APPLICATION_ID", + "ALGOLIA_API_KEY", + ClientOptions.builder().addDefaultHeader("X-Algolia-UserToken", "test-user-123").build() + ); + client.close(); + } +} diff --git a/templates/java/guides/search/mcmSearchWithout.mustache b/templates/java/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..df9edab1b05 --- /dev/null +++ b/templates/java/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,42 @@ +package com.algolia; + +import java.util.List; +import java.util.Map; + +{{> snippets/import}} + +public class mcmSearchWithout { + + private static String getAppIDFor(String user) { + return ""; // Implement your own logic here + } + + private static String getIndexingApiKeyFor(String user) { + return ""; // Implement your own logic here + } + + public static void main(String[] args) throws Exception { + + // Fetch from your own data storage and with your own code + // the associated application ID and API key for this user + String appID = getAppIDFor("user42"); + String apiKey = getIndexingApiKeyFor("user42"); + + try (SearchClient client = new SearchClient(appID, apiKey)) { + SearchParams searchParams = new SearchParamsObject() + .setQuery("") + .setFacetFilters( + FacetFilters.of( + List.of( + FacetFilters.of("user:user42"), + FacetFilters.of("user:public") + ) + ) + ); + + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; + } catch (Exception e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/templates/java/guides/search/saveImageClassifications.mustache b/templates/java/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..0a0bbf4a57d --- /dev/null +++ b/templates/java/guides/search/saveImageClassifications.mustache @@ -0,0 +1,50 @@ +package com.algolia; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +{{> snippets/import}} + +class saveImageClassifications { + + static class Image + { + public String imageURL; + public String objectID; + public List> objects; + + public Image(String imageURL, String objectID, List> objects) { + this.imageURL = imageURL; + this.objectID = objectID; + this.objects = objects; + } + } + + // Retrieve labels + static Image getImageLabels(String imageURL, String objectID, float scoreLimit) + { + // Implement your image classification logic here + return new Image(imageURL, objectID, new ArrayList<>()); + } + + public static void main(String[] args) throws Exception { + + // API key ACL should include editSettings / addObject + try ({{> snippets/init}}) { + + var hits = client.browseObjects("", Image.class); + + List records = new ArrayList<>(); + for (var hit : hits) { + var image = getImageLabels(hit.imageURL, hit.objectID, 0.5f); + records.add(image); + } + + // Update records with image classifications + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}}; + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/templates/java/guides/search/saveImageClassificationsAndSettings.mustache b/templates/java/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..d82303cf105 --- /dev/null +++ b/templates/java/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,79 @@ +package com.algolia; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +{{> snippets/import}} + +class saveImageClassificationsAndSettings { + + static class Image + { + public String imageURL; + public String objectID; + public List> objects; + + public Image(String imageURL, String objectID, List> objects) { + this.imageURL = imageURL; + this.objectID = objectID; + this.objects = objects; + } + } + + // Retrieve labels + static Image getImageLabels(String imageURL, String objectID, float scoreLimit) + { + // Implement your image classification logic here + return new Image(imageURL, objectID, new ArrayList<>()); + } + + public static void main(String[] args) throws Exception { + + // API key ACL should include editSettings / addObject + try ({{> snippets/init}}) { + + var hits = client.browseObjects("", Image.class); + + List records = new ArrayList<>(); + for (var hit : hits) { + var image = getImageLabels(hit.imageURL, hit.objectID, 0.5f); + records.add(image); + } + + // Update records with image classifications + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}}; + + List facets = new ArrayList<>(); + List attributes = new ArrayList<>(); + + records.forEach(record -> { + record.objects.forEach(object -> { + object.forEach((key, values) -> { + if (values instanceof Iterable) { + facets.add("searchable(objects." + key + ".label)"); + facets.add("searchable(objects." + key + ".score)"); + attributes.add("objects." + key + ".label"); + } + }); + }); + }); + + var currentSettings = {{#dynamicSnippet}}getSettings{{/dynamicSnippet}}; + + var attributesForFaceting = currentSettings.getAttributesForFaceting() != null ? currentSettings.getAttributesForFaceting() : new ArrayList(); + var searchableAttributes = currentSettings.getSearchableAttributes() != null ? currentSettings.getSearchableAttributes() : new ArrayList(); + + attributesForFaceting.addAll(facets); + searchableAttributes.addAll(attributes); + + var settings = new IndexSettings() + .setAttributesForFaceting(attributesForFaceting) + .setSearchableAttributes(searchableAttributes); + + {{#dynamicSnippet}}setSettings{{/dynamicSnippet}}; + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/templates/javascript/guides/search/deleteMultipleIndices.mustache b/templates/javascript/guides/search/deleteMultipleIndices.mustache index d7dd9c33b3b..6aa1e9d4f7d 100644 --- a/templates/javascript/guides/search/deleteMultipleIndices.mustache +++ b/templates/javascript/guides/search/deleteMultipleIndices.mustache @@ -1,36 +1,32 @@ {{> snippets/import}} import type { MultipleBatchRequest } from 'algoliasearch'; -try { - // You need an API key with `deleteIndex` - {{> snippets/init}} +// You need an API key with `deleteIndex` +{{> snippets/init}} - // List all indices - const indices = {{#dynamicSnippet}}listIndicesSimple{{/dynamicSnippet}}; +// List all indices +const indices = {{#dynamicSnippet}}listIndicesSimple{{/dynamicSnippet}}; - // Primary indices don't have a `primary` key - const primaryIndices = indices.items.filter(item => item.primary == null); - const replicaIndices = indices.items.filter(item => item.primary != null); +// Primary indices don't have a `primary` key +const primaryIndices = indices.items.filter(item => item.primary == null); +const replicaIndices = indices.items.filter(item => item.primary != null); - // Delete primary indices first - if (primaryIndices.length > 0) { - const requests: MultipleBatchRequest[] = primaryIndices.map(index => ({ - action: 'delete', - indexName: index.name - })); - {{#dynamicSnippet}}deleteMultipleIndicesPrimary{{/dynamicSnippet}}; - console.log("Deleted primary indices."); - } +// Delete primary indices first +if (primaryIndices.length > 0) { + const requests: MultipleBatchRequest[] = primaryIndices.map(index => ({ + action: 'delete', + indexName: index.name + })); + {{#dynamicSnippet}}deleteMultipleIndicesPrimary{{/dynamicSnippet}}; + console.log("Deleted primary indices."); +} - // Now, delete replica indices - if (replicaIndices.length > 0) { - const requests: MultipleBatchRequest[] = replicaIndices.map(index => ({ - action: 'delete', - indexName: index.name - })); - {{#dynamicSnippet}}deleteMultipleIndicesReplica{{/dynamicSnippet}}; - console.log("Deleted replica indices."); - } -} catch (e: any) { - console.error(e); +// Now, delete replica indices +if (replicaIndices.length > 0) { + const requests: MultipleBatchRequest[] = replicaIndices.map(index => ({ + action: 'delete', + indexName: index.name + })); + {{#dynamicSnippet}}deleteMultipleIndicesReplica{{/dynamicSnippet}}; + console.log("Deleted replica indices."); } diff --git a/templates/javascript/guides/search/globalAlgoliaUserID.mustache b/templates/javascript/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..5d37d53546e --- /dev/null +++ b/templates/javascript/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,8 @@ +{{> snippets/import}} + +const client = algoliasearch("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY", { + baseHeaders: { + 'X-Algolia-User-ID': 'test-user-123', + }, +}); +console.log(client); diff --git a/templates/javascript/guides/search/mcmSearchWithout.mustache b/templates/javascript/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..939ee865155 --- /dev/null +++ b/templates/javascript/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,22 @@ +{{> snippets/import}} +import type { SearchParams } from 'algoliasearch'; + +const getAppIDFor = (_: string) => { + return ""; // Implement your own logic here +} +const getIndexingApiKeyFor = (_: string) => { + return ""; // Implement your own logic here +} + +// Fetch from your own data storage and with your own code +// the associated application ID and API key for this user +const appID = getAppIDFor("user42"); +const apiKey = getIndexingApiKeyFor("user42"); + +const client = algoliasearch(appID, apiKey); +const searchParams: SearchParams = { + query: "", + facetFilters: ["user:user42", "user:public"] +}; + +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/saveImageClassifications.mustache b/templates/javascript/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..c6518011379 --- /dev/null +++ b/templates/javascript/guides/search/saveImageClassifications.mustache @@ -0,0 +1,37 @@ +{{> snippets/import}} + +interface Image extends Record { + imageURL: string; + objectID: string; + objects: Record[]; +} + +async function saveImageClassifications() { + // Retrieve labels + function getImageLabels(imageURL, objectID, scoreLimit): Image { + // Implement your image classification logic here + return { imageURL: "", objectID: "", objects: [] }; + } + + // API key ACL should include editSettings / addObject + {{> snippets/init}} + + const records: Image[] = []; + + await client.browseObjects({ + indexName: "", + browseParams: undefined, + aggregator: (browseResponse) => { + records.push(...browseResponse.hits.map(hit => { + return getImageLabels( + hit.imageURL, + hit.objectID, + 0.5 + ); + })); + } + }); + + // Update records with image classifications + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}}; +} \ No newline at end of file diff --git a/templates/javascript/guides/search/saveImageClassificationsAndSettings.mustache b/templates/javascript/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..f60130b5ad5 --- /dev/null +++ b/templates/javascript/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,61 @@ +{{> snippets/import}} + +interface Image extends Record { + imageURL: string; + objectID: string; + objects: Record[]; +} + +async function saveImageClassifications() { + // Retrieve labels + function getImageLabels(imageURL, objectID, scoreLimit): Image { + // Implement your image classification logic here + return { imageURL: "", objectID: "", objects: [] }; + } + + // API key ACL should include editSettings / addObject + {{> snippets/init}} + + const records: Image[] = []; + + await client.browseObjects({ + indexName: "", + browseParams: undefined, + aggregator: (browseResponse) => { + records.push(...browseResponse.hits.map(hit => { + return getImageLabels( + hit.imageURL, + hit.objectID, + 0.5 + ); + })); + } + }); + + // Update records with image classifications + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}}; + + const facets: string[] = []; + const attributes: string[] = []; + + records.forEach(record => { + record.objects.forEach(obj => { + Object.entries(obj).forEach(([key, values]) => { + if (Array.isArray(values)) { // Checking if iterable + facets.push(`searchable(objects.${key}.label)`); + facets.push(`searchable(objects.${key}.score)`); + attributes.push(`objects.${key}.label`); + } + }); + }); + }); + + const currentSettings = {{#dynamicSnippet}}getSettings{{/dynamicSnippet}}; + + const settings = { + searchableAttributes: (currentSettings.searchableAttributes ?? []).concat(attributes ?? []), + attributesForFaceting: (currentSettings.attributesForFaceting ?? []).concat(facets ?? []), + }; + + {{#dynamicSnippet}}setSettings{{/dynamicSnippet}}; +} diff --git a/templates/javascript/guides/search/saveObjectsChunks.mustache b/templates/javascript/guides/search/saveObjectsChunks.mustache index 9c56886534b..b6bbbfaff08 100644 --- a/templates/javascript/guides/search/saveObjectsChunks.mustache +++ b/templates/javascript/guides/search/saveObjectsChunks.mustache @@ -1,17 +1,17 @@ {{> snippets/import}} -try { - {{> snippets/init}} +{{> snippets/init}} - // @ts-ignore - const { default: records } = await import('./actors.json'); +// @ts-ignore +const { default: records } = await import('./actors.json'); - const chunkSize = 10000 +const chunkSize = 10000 - for (let beginIndex = 0; beginIndex < records.length; beginIndex += chunkSize) { +for (let beginIndex = 0; beginIndex < records.length; beginIndex += chunkSize) { + try { const chunk = records.slice(beginIndex, beginIndex + chunkSize); {{#dynamicSnippet}}saveObjectsChunks{{/dynamicSnippet}} + } catch (e: any) { + console.error(e); } -} catch (e: any) { - console.error(e); } diff --git a/templates/javascript/guides/search/saveObjectsModified.mustache b/templates/javascript/guides/search/saveObjectsModified.mustache index 8af564dfc55..862e621fa0c 100644 --- a/templates/javascript/guides/search/saveObjectsModified.mustache +++ b/templates/javascript/guides/search/saveObjectsModified.mustache @@ -1,22 +1,18 @@ {{> snippets/import}} -try { - {{> snippets/init}} +{{> snippets/init}} - // @ts-ignore - const { default: products } = await import('./products.json'); +// @ts-ignore +const { default: products } = await import('./products.json'); - const records = products.map((product) => { - const reference = product["product_reference"]; - const suffixes: string[] = [] +const records = products.map((product) => { + const reference = product["product_reference"]; + const suffixes: string[] = [] - for (let i = reference.length; i > 1; i--) { - suffixes.unshift(reference.slice(i)); - } - return { ...product, product_reference_suffixes: suffixes }; - }); + for (let i = reference.length; i > 1; i--) { + suffixes.unshift(reference.slice(i)); + } + return { ...product, product_reference_suffixes: suffixes }; +}); - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} -} catch (e: any) { - console.error(e); -} +{{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/saveObjectsPublicUser.mustache b/templates/javascript/guides/search/saveObjectsPublicUser.mustache index 05779acc63b..397ed17c18a 100644 --- a/templates/javascript/guides/search/saveObjectsPublicUser.mustache +++ b/templates/javascript/guides/search/saveObjectsPublicUser.mustache @@ -2,10 +2,6 @@ const playlists: Record[] = [] // Your records -try { - {{> snippets/init}} +{{> snippets/init}} - {{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}} -} catch (e: any) { - console.error(e); -} \ No newline at end of file +{{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/savePopularRecords.mustache b/templates/javascript/guides/search/savePopularRecords.mustache index 8b20632b934..c522b2eab1e 100644 --- a/templates/javascript/guides/search/savePopularRecords.mustache +++ b/templates/javascript/guides/search/savePopularRecords.mustache @@ -1,20 +1,16 @@ {{> snippets/import}} -try { - {{> snippets/init}} +{{> snippets/init}} - const records: Array> = []; +const records: Array> = []; - await client.browseObjects>({ indexName: "", browseParams: undefined, aggregator: (res) => - records.push( - res.hits.map((record) => ({ - ...record, - isPopular: record.nbFollowers >= 1_000_000, - })) - ) - }); +await client.browseObjects>({ indexName: "", browseParams: undefined, aggregator: (res) => + records.push( + res.hits.map((record) => ({ + ...record, + isPopular: record.nbFollowers >= 1_000_000, + })) + ) +}); - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} -} catch (e: any) { - console.error(e); -} +{{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/searchFuturePublishedBooks.mustache b/templates/javascript/guides/search/searchFuturePublishedBooks.mustache index 8d0688a2bf8..4eb9291a7f1 100644 --- a/templates/javascript/guides/search/searchFuturePublishedBooks.mustache +++ b/templates/javascript/guides/search/searchFuturePublishedBooks.mustache @@ -1,16 +1,12 @@ {{> snippets/import}} import type { SearchParams } from 'algoliasearch'; -try { - {{> snippets/init}} +{{> snippets/init}} - const dateTimestamp = Date.now(); - const searchParams: SearchParams = { - query: "", - filters: `date_timestamp > ${dateTimestamp}` - }; +const dateTimestamp = Date.now(); +const searchParams: SearchParams = { + query: "", + filters: `date_timestamp > ${dateTimestamp}` +}; - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} -} catch (e: any) { - console.error(e); -} +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/searchInReplicaIndex.mustache b/templates/javascript/guides/search/searchInReplicaIndex.mustache index 23bf03a2a43..108cfa3cd67 100644 --- a/templates/javascript/guides/search/searchInReplicaIndex.mustache +++ b/templates/javascript/guides/search/searchInReplicaIndex.mustache @@ -1,18 +1,14 @@ {{> snippets/import}} -try { - {{> snippets/init}} +{{> snippets/init}} - const query = 'query'; +const query = 'query'; - // 1. Change the sort dynamically based on the UI events - const sortByPrice = false; +// 1. Change the sort dynamically based on the UI events +const sortByPrice = false; - // 2. Get the index name based on sortByPrice - const indexName = sortByPrice ? 'products_price_desc' : 'products'; +// 2. Get the index name based on sortByPrice +const indexName = sortByPrice ? 'products_price_desc' : 'products'; - // 3. Search on dynamic index name (primary or replica) - {{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}}; -} catch (e: any) { - console.error(e.message); -} +// 3. Search on dynamic index name (primary or replica) +{{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}}; diff --git a/templates/javascript/guides/search/searchRecentlyPublishedBooks.mustache b/templates/javascript/guides/search/searchRecentlyPublishedBooks.mustache index 8a1fd7050f8..db9aa824acd 100644 --- a/templates/javascript/guides/search/searchRecentlyPublishedBooks.mustache +++ b/templates/javascript/guides/search/searchRecentlyPublishedBooks.mustache @@ -1,16 +1,12 @@ {{> snippets/import}} import type { SearchParams } from 'algoliasearch'; -try { - {{> snippets/init}} +{{> snippets/init}} - const d = new Date(); - const searchParams: SearchParams = { - query: "", - filters: `date_timestamp > ${Math.floor(d.setDate(d.getDate() - 365) / 1000)}` - }; +const d = new Date(); +const searchParams: SearchParams = { + query: "", + filters: `date_timestamp > ${Math.floor(d.setDate(d.getDate() - 365) / 1000)}` +}; - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} -} catch (e: any) { - console.error(e); -} +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/searchWithAnalyticsAndHeader.mustache b/templates/javascript/guides/search/searchWithAnalyticsAndHeader.mustache index c06c44a8446..c98e2238d9f 100644 --- a/templates/javascript/guides/search/searchWithAnalyticsAndHeader.mustache +++ b/templates/javascript/guides/search/searchWithAnalyticsAndHeader.mustache @@ -2,23 +2,19 @@ import type { SearchParamsObject } from 'algoliasearch'; -try { - {{> snippets/init}} +{{> snippets/init}} - /* - '94.228.178.246' should be replaced with your user's IP address. - Depending on your stack there are multiple ways to get this information. - */ - const ip = '94.228.178.246'; - const query = 'query'; +/* +'94.228.178.246' should be replaced with your user's IP address. +Depending on your stack there are multiple ways to get this information. +*/ +const ip = '94.228.178.246'; +const query = 'query'; - const searchParams: SearchParamsObject = { - query, - analytics: true, - }; +const searchParams: SearchParamsObject = { + query, + analytics: true, +}; - {{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}}; -} catch (e: any) { - console.error(e); -} +{{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}}; diff --git a/templates/javascript/guides/search/searchWithGAToken.mustache b/templates/javascript/guides/search/searchWithGAToken.mustache index 22029b30c91..e91c9ef7ce4 100644 --- a/templates/javascript/guides/search/searchWithGAToken.mustache +++ b/templates/javascript/guides/search/searchWithGAToken.mustache @@ -5,21 +5,17 @@ const getGoogleAnalyticsUserIdFromBrowserCookie = (_: string) => { return ""; // Implement your logic here } -try { - {{> snippets/init}} +{{> snippets/init}} - const userToken = getGoogleAnalyticsUserIdFromBrowserCookie('_ga'); - let searchParams: SearchParams = { - query: "", - userToken - }; +const userToken = getGoogleAnalyticsUserIdFromBrowserCookie('_ga'); +let searchParams: SearchParams = { + query: "", + userToken +}; - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - const loggedInUser: string | undefined = undefined; - searchParams.userToken = loggedInUser ?? userToken; +const loggedInUser: string | undefined = undefined; +searchParams.userToken = loggedInUser ?? userToken; - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} -} catch (e: any) { - console.error(e); -} \ No newline at end of file +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/searchWithLogicalOr.mustache b/templates/javascript/guides/search/searchWithLogicalOr.mustache index 6d0aaa78632..72de8824f85 100644 --- a/templates/javascript/guides/search/searchWithLogicalOr.mustache +++ b/templates/javascript/guides/search/searchWithLogicalOr.mustache @@ -1,15 +1,11 @@ {{> snippets/import}} import type { SearchParamsObject, OptionalWords } from 'algoliasearch'; -try { - {{> snippets/init}} - const query = 'the query'; - const optionalWords: OptionalWords = ['the', 'query']; - const searchParams: SearchParamsObject = { - query, - optionalWords - }; - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; -} catch (e: any) { - console.error(e.message); -} \ No newline at end of file +{{> snippets/init}} +const query = 'the query'; +const optionalWords: OptionalWords = ['the', 'query']; +const searchParams: SearchParamsObject = { + query, + optionalWords +}; +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; diff --git a/templates/javascript/guides/search/searchWithOptionalFilters.mustache b/templates/javascript/guides/search/searchWithOptionalFilters.mustache index b3170925ec9..e6adff37850 100644 --- a/templates/javascript/guides/search/searchWithOptionalFilters.mustache +++ b/templates/javascript/guides/search/searchWithOptionalFilters.mustache @@ -7,16 +7,12 @@ const reduceLabelsToFilters = (_labels: string[]): OptionalFilters => { return []; // Implement your logic here } -try { - {{> snippets/init}} +{{> snippets/init}} - const optionalFilters = reduceLabelsToFilters(labels) - const searchParams: SearchParams = { - query: "", - optionalFilters: optionalFilters - }; +const optionalFilters = reduceLabelsToFilters(labels) +const searchParams: SearchParams = { + query: "", + optionalFilters: optionalFilters +}; - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} -} catch (e: any) { - console.error(e); -} +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/searchWithRuleContextBuyer.mustache b/templates/javascript/guides/search/searchWithRuleContextBuyer.mustache index 34343d4129d..d096e6829e3 100644 --- a/templates/javascript/guides/search/searchWithRuleContextBuyer.mustache +++ b/templates/javascript/guides/search/searchWithRuleContextBuyer.mustache @@ -5,17 +5,13 @@ const getBuyerAccountId = () => { return ""; // Implement your logic here } -try { - {{> snippets/init}} +{{> snippets/init}} - // get the buyer account information - const buyer = getBuyerAccountId(); - const searchParams: SearchParams = { - query: "", - ruleContexts: [buyer] - }; +// get the buyer account information +const buyer = getBuyerAccountId(); +const searchParams: SearchParams = { + query: "", + ruleContexts: [buyer] +}; - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} -} catch (e: any) { - console.error(e); -} +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/searchWithRuleContexts.mustache b/templates/javascript/guides/search/searchWithRuleContexts.mustache index 12f93bce7e2..4eeadd8ec0b 100644 --- a/templates/javascript/guides/search/searchWithRuleContexts.mustache +++ b/templates/javascript/guides/search/searchWithRuleContexts.mustache @@ -5,16 +5,12 @@ const getPlatformTag = () => { return ""; // Implement your logic here } -try { - {{> snippets/init}} +{{> snippets/init}} - const platformTag = getPlatformTag(); - const searchParams: SearchParams = { - query: "", - ruleContexts: [platformTag] - }; +const platformTag = getPlatformTag(); +const searchParams: SearchParams = { + query: "", + ruleContexts: [platformTag] +}; - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} -} catch (e: any) { - console.error(e); -} +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/javascript/guides/search/setHeaderUserIDThenSaveObjects.mustache b/templates/javascript/guides/search/setHeaderUserIDThenSaveObjects.mustache index 8e1bab24ca2..cc57ae7a6b6 100644 --- a/templates/javascript/guides/search/setHeaderUserIDThenSaveObjects.mustache +++ b/templates/javascript/guides/search/setHeaderUserIDThenSaveObjects.mustache @@ -2,13 +2,13 @@ const playlists: Record[] = [/* Your records */]; -try { - {{> snippets/init}} +{{> snippets/init}} - playlists.forEach(async (playlist) => { +playlists.forEach(async (playlist) => { + try { const playlistUserID = playlist["userID"]; {{#dynamicSnippet}}saveObjectsPlaylistsWithRequestOptions{{/dynamicSnippet}} - }); -} catch (e: any) { - console.error(e); -} \ No newline at end of file + } catch (e: any) { + console.error(e); + } +}); diff --git a/templates/javascript/guides/search/useConditionlessRule.mustache b/templates/javascript/guides/search/useConditionlessRule.mustache index 798ae57a0f7..31e3d3a321c 100644 --- a/templates/javascript/guides/search/useConditionlessRule.mustache +++ b/templates/javascript/guides/search/useConditionlessRule.mustache @@ -1,27 +1,23 @@ {{> snippets/import}} import type { Rule } from 'algoliasearch'; -try { - {{> snippets/init}} +{{> snippets/init}} - const objectID = 'a-rule-id'; +const objectID = 'a-rule-id'; - const rule: Rule = { - objectID, - consequence: { - // Set relevant consequence - }, - }; +const rule: Rule = { + objectID, + consequence: { + // Set relevant consequence + }, +}; - // Set validity (optional) - rule.validity = [ - { - from: 1688774400, - until: 1738972800, - }, - ]; +// Set validity (optional) +rule.validity = [ + { + from: 1688774400, + until: 1738972800, + }, +]; - {{#dynamicSnippet}}saveRule{{/dynamicSnippet}}; -} catch (e: any) { - console.error(e.message); -} \ No newline at end of file +{{#dynamicSnippet}}saveRule{{/dynamicSnippet}}; diff --git a/templates/kotlin/guides/search/globalAlgoliaUserID.mustache b/templates/kotlin/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..76ad6b80272 --- /dev/null +++ b/templates/kotlin/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,11 @@ +{{> snippets/import}} +import com.algolia.client.model.search.* + +suspend fun globalAlgoliaUserID() { + val client = SearchClient( + appId = "ALGOLIA_APPLICATION_ID", + apiKey = "ALGOLIA_API_KEY", + options = ClientOptions(defaultHeaders = mapOf("X-Algolia-User-ID" to "test-user-123")) + ) + println(client.options.defaultHeaders) +} diff --git a/templates/kotlin/guides/search/mcmSearchWithout.mustache b/templates/kotlin/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..be3ad815abb --- /dev/null +++ b/templates/kotlin/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,31 @@ +import kotlinx.serialization.json.JsonObject + +{{> snippets/import}} +import com.algolia.client.model.search.* + +suspend fun mcmSearchWithout() { + val getAppIDFor: (String) -> String = { + "" // Implement your own logic here + } + val getIndexingApiKeyFor: (String) -> String = { + "" // Implement your own logic here + } + + // Fetch from your own data storage and with your own code + // the associated application ID and API key for this user + val appID = getAppIDFor("user42"); + val apiKey = getIndexingApiKeyFor("user42"); + + val client = SearchClient(appID, apiKey) + val searchParams = SearchParamsObject( + query = "", + facetFilters = FacetFilters.of( + listOf( + FacetFilters.of("user:user42"), + FacetFilters.of("user:public") + ) + ) + ) + + client.{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} +} \ No newline at end of file diff --git a/templates/kotlin/guides/search/saveImageClassifications.mustache b/templates/kotlin/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..8569cf23745 --- /dev/null +++ b/templates/kotlin/guides/search/saveImageClassifications.mustache @@ -0,0 +1,47 @@ +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.encodeToJsonElement +import kotlinx.serialization.json.jsonObject + +{{> snippets/import}} +import com.algolia.client.model.search.BrowseParamsObject + +suspend fun saveImageClassifications() { + data class Image( + val imageURL: String, + val objectID: String, + val objects: List> + ) + + // Retrieve labels + fun getImageLabels(imageURL: String, objectID: String, scoreLimit: Float): Image { + // Implement your image classification logic here + return Image(imageURL, objectID, emptyList()) + } + + // API key ACL should include editSettings / addObject + try { + {{> snippets/init}} + + val images: MutableList = mutableListOf() + + client.browseObjects( + indexName = "", + params = BrowseParamsObject(), + aggregator = { browseResponse -> + images.addAll( + browseResponse.hits.map { + val props = it.additionalProperties ?: emptyMap() + return@map getImageLabels(props.getOrElse("imageURL") { "" }.toString(), it.objectID, 0.5f) + }, + ) + }, + ) + + val records = images.map { Json.encodeToJsonElement(it).jsonObject } + + // Update records with image classifications + client.{{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} + } catch (e: Exception) { + println(e.message); + } +} diff --git a/templates/kotlin/guides/search/saveImageClassificationsAndSettings.mustache b/templates/kotlin/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..840afefab28 --- /dev/null +++ b/templates/kotlin/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,72 @@ +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.encodeToJsonElement +import kotlinx.serialization.json.jsonObject + +{{> snippets/import}} +import com.algolia.client.model.search.BrowseParamsObject +import com.algolia.client.model.search.IndexSettings + +suspend fun saveImageClassificationsAndSettings() { + data class Image( + val imageURL: String, + val objectID: String, + val objects: List> + ) + + // Retrieve labels + fun getImageLabels(imageURL: String, objectID: String, scoreLimit: Float): Image { + // Implement your image classification logic here + return Image(imageURL, objectID, emptyList()) + } + + // API key ACL should include editSettings / addObject + try { + {{> snippets/init}} + + val images: MutableList = mutableListOf() + + client.browseObjects( + indexName = "", + params = BrowseParamsObject(), + aggregator = { browseResponse -> + images.addAll( + browseResponse.hits.map { + val props = it.additionalProperties ?: emptyMap() + return@map getImageLabels(props.getOrElse("imageURL") { "" }.toString(), it.objectID, 0.5f) + }, + ) + }, + ) + + val records = images.map { Json.encodeToJsonElement(it).jsonObject } + + // Update records with image classifications + client.{{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} + + val facets = mutableListOf() + val attributes = mutableListOf() + + images.forEach { record -> + record.objects.forEach { obj -> + obj.forEach { (key, values) -> + if (values is Iterable<*>) { + facets.add("searchable(objects.$key.label)") + facets.add("searchable(objects.$key.score)") + attributes.add("objects.$key.label") + } + } + } + } + + val currentSettings = client.{{#dynamicSnippet}}getSettings{{/dynamicSnippet}} + + val settings = IndexSettings( + searchableAttributes = currentSettings.searchableAttributes?.plus(attributes), + attributesForFaceting = currentSettings.attributesForFaceting?.plus(facets), + ) + + client.{{#dynamicSnippet}}setSettings{{/dynamicSnippet}} + } catch (e: Exception) { + println(e.message); + } +} diff --git a/templates/php/guides/search/deleteMultipleIndices.mustache b/templates/php/guides/search/deleteMultipleIndices.mustache index c63766983a6..3e559eee8c2 100644 --- a/templates/php/guides/search/deleteMultipleIndices.mustache +++ b/templates/php/guides/search/deleteMultipleIndices.mustache @@ -5,46 +5,42 @@ require __DIR__.'/../vendor/autoload.php'; use Algolia\AlgoliaSearch\Model\Search\Action; use Algolia\AlgoliaSearch\Model\Search\MultipleBatchRequest; -try { - // You need an API key with `deleteIndex` - {{> snippets/init}}; - - // List all indices - $indicesResponse = {{#dynamicSnippet}}listIndicesSimple{{/dynamicSnippet}}; - $indices = $indicesResponse['items']; - - // Primary indices don't have a `primary` key - $primaryIndices = array_filter($indices, function ($index) { - return !isset($index['primary']); - }); - $replicaIndices = array_filter($indices, function ($index) { - return isset($index['primary']); - }); - - // Delete primary indices first - if (!empty($primaryIndices)) { - $requests = array_map(function ($index) { - return (new MultipleBatchRequest()) - ->setAction((new Action())::DELETE) - ->setIndexName($index['name']); - }, $primaryIndices); - - {{#dynamicSnippet}}deleteMultipleIndicesPrimary{{/dynamicSnippet}}; - echo "Deleted primary indices.\n"; - } - - // Now, delete replica indices - if (!empty($replicaIndices)) { - $requests = array_map(function ($index) { - return [ - 'action' => 'delete', - 'indexName' => $index['name'], - ]; - }, $replicaIndices); - - {{#dynamicSnippet}}deleteMultipleIndicesReplica{{/dynamicSnippet}}; - echo "Deleted replica indices.\n"; - } -} catch (Exception $e) { - echo 'Error: ' . $e->getMessage() . "\n"; +// You need an API key with `deleteIndex` +{{> snippets/init}}; + +// List all indices +$indicesResponse = {{#dynamicSnippet}}listIndicesSimple{{/dynamicSnippet}}; +$indices = $indicesResponse['items']; + +// Primary indices don't have a `primary` key +$primaryIndices = array_filter($indices, function ($index) { + return !isset($index['primary']); +}); +$replicaIndices = array_filter($indices, function ($index) { + return isset($index['primary']); +}); + +// Delete primary indices first +if (!empty($primaryIndices)) { + $requests = array_map(function ($index) { + return (new MultipleBatchRequest()) + ->setAction((new Action())::DELETE) + ->setIndexName($index['name']); + }, $primaryIndices); + + {{#dynamicSnippet}}deleteMultipleIndicesPrimary{{/dynamicSnippet}}; + echo "Deleted primary indices.\n"; +} + +// Now, delete replica indices +if (!empty($replicaIndices)) { + $requests = array_map(function ($index) { + return [ + 'action' => 'delete', + 'indexName' => $index['name'], + ]; + }, $replicaIndices); + + {{#dynamicSnippet}}deleteMultipleIndicesReplica{{/dynamicSnippet}}; + echo "Deleted replica indices.\n"; } diff --git a/templates/php/guides/search/globalAlgoliaUserID.mustache b/templates/php/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..1cfb4262c3b --- /dev/null +++ b/templates/php/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,9 @@ + snippets/import}} + +$config = SearchConfig::create('ALGOLIA_APPLICATION_ID', 'ALGOLIA_API_KEY'); +$config->setDefaultHeaders(['X-Algolia-UserToken' => 'test-user-123']); +$client = SearchClient::createWithConfig($config); +echo $client->getClientConfig()->getDefaultHeaders(); diff --git a/templates/php/guides/search/mcmSearchWithout.mustache b/templates/php/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..e14ca7ca34f --- /dev/null +++ b/templates/php/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,26 @@ + snippets/import}} +use Algolia\AlgoliaSearch\Model\Search\SearchParamsObject; + +$getAppIDFor = function ($user) { + return ""; // Implement your own logic here +}; + +$getIndexingApiKeyFor = function ($user) { + return ""; // Implement your own logic here +}; + +// Fetch from your own data storage and with your own code +// the associated application ID and API key for this user +$appID = $getAppIDFor('user42'); +$apiKey = $getIndexingApiKeyFor('user42'); + +$client = SearchClient::create($appID, $apiKey); + +$searchParams = (new SearchParamsObject()) + ->setQuery('') + ->setFacetFilters(['user:user42', 'user:public']); + +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/saveImageClassifications.mustache b/templates/php/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..e8fee0deb82 --- /dev/null +++ b/templates/php/guides/search/saveImageClassifications.mustache @@ -0,0 +1,21 @@ + snippets/import}} +use Algolia\AlgoliaSearch\Model\Search\IndexSettings; + +$getImageLabels = function ($imageURL, $objectID, $scoreLimit) { + // Implement your image classification logic here + return ["objectID" => "", "imageURL" => "", "objects" => []]; +}; + +{{> snippets/init}} + +$records = []; + +$hits = $client->browseObjects(''); +foreach ($hits as $hit) { + $imageURL = $hit['imageURL']; + $records[] = $getImageLabels($imageURL, $hit['objectID'], 0.5); +} + +{{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/saveImageClassificationsAndSettings.mustache b/templates/php/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..2b88bd9aa86 --- /dev/null +++ b/templates/php/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,44 @@ + snippets/import}} +use Algolia\AlgoliaSearch\Model\Search\IndexSettings; + +$getImageLabels = function ($imageURL, $objectID, $scoreLimit) { + // Implement your image classification logic here + return ["objectID" => "", "imageURL" => "", "objects" => []]; +}; + +{{> snippets/init}} + +$records = []; + +$hits = $client->browseObjects(''); +foreach ($hits as $hit) { + $imageURL = $hit['imageURL']; + $records[] = $getImageLabels($imageURL, $hit['objectID'], 0.5); +} + +{{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}}; + +$facets = []; +$attributes = []; + +foreach ($records as $record) { + foreach ($record["objects"] as $obj) { + foreach ($obj as $key => $values) { + if (is_array($values)) { + $facets[] = "searchable(objects.$key.label)"; + $facets[] = "searchable(objects.$key.score)"; + $attributes[] = "objects.$key.label)"; + } + } + } +} + +$currentSettings = {{#dynamicSnippet}}getSettings{{/dynamicSnippet}}; + +$settings = (new IndexSettings()) + ->setSearchableAttributes(array_merge($currentSettings->searchableAttributes ?? [], $attributes)) + ->setAttributesForFaceting(array_merge($currentSettings->attributesForFaceting ?? [], $facets)); + +{{#dynamicSnippet}}setSettings{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/saveObjectsChunks.mustache b/templates/php/guides/search/saveObjectsChunks.mustache index f298e712c4c..db9e3d64c1f 100644 --- a/templates/php/guides/search/saveObjectsChunks.mustache +++ b/templates/php/guides/search/saveObjectsChunks.mustache @@ -3,34 +3,34 @@ require __DIR__.'/../vendor/autoload.php'; {{> snippets/import}} -try { - {{> snippets/init}} +{{> snippets/init}} - $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . "actors.json"; +$path = dirname(__FILE__) . DIRECTORY_SEPARATOR . "actors.json"; - if (!file_exists($path)) { - throw new Exception("File not found: $path"); - } +if (!file_exists($path)) { + throw new Exception("File not found: $path"); +} - $data = file_get_contents($path); +$data = file_get_contents($path); - if ($data === false) { - throw new Exception("Failed to read file: $path"); - } +if ($data === false) { + throw new Exception("Failed to read file: $path"); +} - $records = json_decode($data, true); +$records = json_decode($data, true); - if (json_last_error() !== JSON_ERROR_NONE) { - throw new Exception("JSON decode error: " . json_last_error_msg()); - } +if (json_last_error() !== JSON_ERROR_NONE) { + throw new Exception("JSON decode error: " . json_last_error_msg()); +} - $chunkSize = 10000; +$chunkSize = 10000; - for ($beginIndex = 0; $beginIndex < count($records); $beginIndex += $chunkSize) { - $chunk = array_slice($records, $beginIndex, $chunkSize); +for ($beginIndex = 0; $beginIndex < count($records); $beginIndex += $chunkSize) { + $chunk = array_slice($records, $beginIndex, $chunkSize); + try { {{#dynamicSnippet}}saveObjectsChunks{{/dynamicSnippet}}; + } catch (Exception $e) { + echo 'Error: ' . $e->getMessage() . "\n"; } -} catch (Exception $e) { - echo 'Error: ' . $e->getMessage() . "\n"; } diff --git a/templates/php/guides/search/saveObjectsModified.mustache b/templates/php/guides/search/saveObjectsModified.mustache index 0d6562d7d0f..38d94dd5ad1 100644 --- a/templates/php/guides/search/saveObjectsModified.mustache +++ b/templates/php/guides/search/saveObjectsModified.mustache @@ -3,41 +3,37 @@ require __DIR__.'/../vendor/autoload.php'; {{> snippets/import}} -try { - {{> snippets/init}} +{{> snippets/init}} - $path = dirname(__FILE__) . DIRECTORY_SEPARATOR . "products.json"; +$path = dirname(__FILE__) . DIRECTORY_SEPARATOR . "products.json"; - if (!file_exists($path)) { - throw new Exception("File not found: $path"); - } +if (!file_exists($path)) { + throw new Exception("File not found: $path"); +} - $data = file_get_contents($path); +$data = file_get_contents($path); - if ($data === false) { - throw new Exception("Failed to read file: $path"); - } +if ($data === false) { + throw new Exception("Failed to read file: $path"); +} - $products = json_decode($data, true); +$products = json_decode($data, true); - if (json_last_error() !== JSON_ERROR_NONE) { - throw new Exception("JSON decode error: " . json_last_error_msg()); - } +if (json_last_error() !== JSON_ERROR_NONE) { + throw new Exception("JSON decode error: " . json_last_error_msg()); +} - $records = array_map(function ($product) { - $reference = $product['product_reference']; - $suffixes = []; +$records = array_map(function ($product) { + $reference = $product['product_reference']; + $suffixes = []; - while (strlen($reference) > 1) { - $reference = substr($reference, 1); - $suffixes[] = $reference; - } + while (strlen($reference) > 1) { + $reference = substr($reference, 1); + $suffixes[] = $reference; + } - $product['product_reference_suffixes'] = $suffixes; - return $product; - }, $products); + $product['product_reference_suffixes'] = $suffixes; + return $product; +}, $products); - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} +{{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/saveObjectsPublicUser.mustache b/templates/php/guides/search/saveObjectsPublicUser.mustache index 66512f3aa27..3c661f7dd07 100644 --- a/templates/php/guides/search/saveObjectsPublicUser.mustache +++ b/templates/php/guides/search/saveObjectsPublicUser.mustache @@ -5,10 +5,6 @@ require __DIR__.'/../vendor/autoload.php'; $playlists = [ /* Your records */ ]; -try { - {{> snippets/init}} +{{> snippets/init}} - {{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} \ No newline at end of file +{{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/savePopularRecords.mustache b/templates/php/guides/search/savePopularRecords.mustache index ea70d1e6344..6a53b24a01e 100644 --- a/templates/php/guides/search/savePopularRecords.mustache +++ b/templates/php/guides/search/savePopularRecords.mustache @@ -3,21 +3,17 @@ require __DIR__.'/../vendor/autoload.php'; {{> snippets/import}} -try { - {{> snippets/init}} +{{> snippets/init}} - $results = $client->browseObjects(''); +$results = $client->browseObjects(''); - $records = []; - foreach ($results as $hit) { - $records[] = [ - 'twitterHandle' => $hit['twitterHandle'], - 'nbFollowers' => $hit['nbFollowers'], - 'isPopular' => $hit['nbFollowers'] > 1000000, - ]; - } +$records = []; +foreach ($results as $hit) { + $records[] = [ + 'twitterHandle' => $hit['twitterHandle'], + 'nbFollowers' => $hit['nbFollowers'], + 'isPopular' => $hit['nbFollowers'] > 1000000, + ]; +} - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} \ No newline at end of file +{{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/searchFuturePublishedBooks.mustache b/templates/php/guides/search/searchFuturePublishedBooks.mustache index 2fa8038c8c9..abecc1ceffa 100644 --- a/templates/php/guides/search/searchFuturePublishedBooks.mustache +++ b/templates/php/guides/search/searchFuturePublishedBooks.mustache @@ -4,15 +4,11 @@ require __DIR__.'/../vendor/autoload.php'; {{> snippets/import}} use Algolia\AlgoliaSearch\Model\Search\SearchParamsObject; -try { - {{> snippets/init}} +{{> snippets/init}} - $dateTimestamp = time(); - $searchParams = (new SearchParamsObject()) - ->setQuery('') - ->setFilters("date_timestamp > " . $dateTimestamp); +$dateTimestamp = time(); +$searchParams = (new SearchParamsObject()) + ->setQuery('') + ->setFilters("date_timestamp > " . $dateTimestamp); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} \ No newline at end of file +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/searchInReplicaIndex.mustache b/templates/php/guides/search/searchInReplicaIndex.mustache index 39560acde6e..60fc116ee62 100644 --- a/templates/php/guides/search/searchInReplicaIndex.mustache +++ b/templates/php/guides/search/searchInReplicaIndex.mustache @@ -4,20 +4,16 @@ require __DIR__ . '/../vendor/autoload.php'; {{> snippets/import}} use Algolia\AlgoliaSearch\Model\Search\SearchParamsObject; -try { - {{> snippets/init}} +{{> snippets/init}} - $query = 'query'; +$query = 'query'; - // 1. Change the sort dynamically based on the UI events - $sortByPrice = false; +// 1. Change the sort dynamically based on the UI events +$sortByPrice = false; - // 2. Get the index name based on sortByPrice - $indexName = $sortByPrice ? 'products_price_desc' : 'products'; +// 2. Get the index name based on sortByPrice +$indexName = $sortByPrice ? 'products_price_desc' : 'products'; - // 3. Search on dynamic index name (primary or replica) - {{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} +// 3. Search on dynamic index name (primary or replica) +{{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/searchRecentlyPublishedBooks.mustache b/templates/php/guides/search/searchRecentlyPublishedBooks.mustache index f794eff795e..ed80a06e23b 100644 --- a/templates/php/guides/search/searchRecentlyPublishedBooks.mustache +++ b/templates/php/guides/search/searchRecentlyPublishedBooks.mustache @@ -4,15 +4,11 @@ require __DIR__.'/../vendor/autoload.php'; {{> snippets/import}} use Algolia\AlgoliaSearch\Model\Search\SearchParamsObject; -try { - {{> snippets/init}} +{{> snippets/init}} - $dateTimestamp = strtotime('-1 years'); - $searchParams = (new SearchParamsObject()) - ->setQuery('') - ->setFilters("date_timestamp > " . $dateTimestamp); +$dateTimestamp = strtotime('-1 years'); +$searchParams = (new SearchParamsObject()) + ->setQuery('') + ->setFilters("date_timestamp > " . $dateTimestamp); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} \ No newline at end of file +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/searchWithAnalyticsAndHeader.mustache b/templates/php/guides/search/searchWithAnalyticsAndHeader.mustache index dac624c91dc..b4611dd6135 100644 --- a/templates/php/guides/search/searchWithAnalyticsAndHeader.mustache +++ b/templates/php/guides/search/searchWithAnalyticsAndHeader.mustache @@ -4,22 +4,18 @@ require __DIR__ . '/../vendor/autoload.php'; {{> snippets/import}} use Algolia\AlgoliaSearch\Model\Search\SearchParamsObject; -try { - {{> snippets/init}} +{{> snippets/init}} - /* - '94.228.178.246' should be replaced with your user's IP address. - Depending on your stack there are multiple ways to get this information. - */ - $ip = '94.228.178.246'; - $query = 'query'; +/* +'94.228.178.246' should be replaced with your user's IP address. +Depending on your stack there are multiple ways to get this information. +*/ +$ip = '94.228.178.246'; +$query = 'query'; - $searchParams = (new SearchParamsObject()) - ->setQuery($query) - ->setAnalytics(true); +$searchParams = (new SearchParamsObject()) + ->setQuery($query) + ->setAnalytics(true); - {{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} +{{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/searchWithGAToken.mustache b/templates/php/guides/search/searchWithGAToken.mustache index 3a6444ea810..e4f518c151d 100644 --- a/templates/php/guides/search/searchWithGAToken.mustache +++ b/templates/php/guides/search/searchWithGAToken.mustache @@ -9,22 +9,18 @@ $getGoogleAnalyticsUserIdFromBrowserCookie = function (string $cookieName): stri return ''; }; -try { - {{> snippets/init}} +{{> snippets/init}} - $userToken = $getGoogleAnalyticsUserIdFromBrowserCookie('_ga'); - $searchParams = (new SearchParamsObject()) - ->setQuery('') - ->setUserToken($userToken); +$userToken = $getGoogleAnalyticsUserIdFromBrowserCookie('_ga'); +$searchParams = (new SearchParamsObject()) + ->setQuery('') + ->setUserToken($userToken); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; - /** @var string|null $loggedInUser */ - $loggedInUser = null; +/** @var string|null $loggedInUser */ +$loggedInUser = null; - $searchParams->setUserToken($loggedInUser ?? $userToken); +$searchParams->setUserToken($loggedInUser ?? $userToken); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} \ No newline at end of file +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/searchWithLogicalOr.mustache b/templates/php/guides/search/searchWithLogicalOr.mustache index 7decff1ca7a..5269cfc49c1 100644 --- a/templates/php/guides/search/searchWithLogicalOr.mustache +++ b/templates/php/guides/search/searchWithLogicalOr.mustache @@ -5,20 +5,16 @@ require __DIR__ . '/../vendor/autoload.php'; use Algolia\AlgoliaSearch\Model\Search\OptionalWords; use Algolia\AlgoliaSearch\Model\Search\SearchParamsObject; -try { - {{> snippets/init}} +{{> snippets/init}} - $query = 'the query'; +$query = 'the query'; - $optionalWords = new OptionalWords(); - $optionalWords[] = $query; +$optionalWords = new OptionalWords(); +$optionalWords[] = $query; - $searchParams = (new SearchParamsObject()) - ->setQuery($query) - ->setOptionalWords($optionalWords); +$searchParams = (new SearchParamsObject()) + ->setQuery($query) + ->setOptionalWords($optionalWords); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/searchWithOptionalFilters.mustache b/templates/php/guides/search/searchWithOptionalFilters.mustache index d99fe42f1f2..89f44b8d392 100644 --- a/templates/php/guides/search/searchWithOptionalFilters.mustache +++ b/templates/php/guides/search/searchWithOptionalFilters.mustache @@ -11,15 +11,11 @@ $reduceLabelsToFilters = function (array $labels): OptionalFilters { return new OptionalFilters(); }; -try { - {{> snippets/init}} +{{> snippets/init}} - $optionalFilters = $reduceLabelsToFilters($labels); - $searchParams = (new SearchParamsObject()) - ->setQuery('') - ->setOptionalFilters($optionalFilters); +$optionalFilters = $reduceLabelsToFilters($labels); +$searchParams = (new SearchParamsObject()) + ->setQuery('') + ->setOptionalFilters($optionalFilters); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} \ No newline at end of file +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/searchWithRuleContextBuyer.mustache b/templates/php/guides/search/searchWithRuleContextBuyer.mustache index 71b8512e488..feed3b64802 100644 --- a/templates/php/guides/search/searchWithRuleContextBuyer.mustache +++ b/templates/php/guides/search/searchWithRuleContextBuyer.mustache @@ -9,16 +9,12 @@ $getBuyerAccountId = function (): string { return ''; }; -try { - {{> snippets/init}} +{{> snippets/init}} - // get the buyer account information - $buyer = $getBuyerAccountId(); - $searchParams = (new SearchParamsObject()) - ->setQuery('') - ->setRuleContexts([$buyer]); +// get the buyer account information +$buyer = $getBuyerAccountId(); +$searchParams = (new SearchParamsObject()) + ->setQuery('') + ->setRuleContexts([$buyer]); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} \ No newline at end of file +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/searchWithRuleContexts.mustache b/templates/php/guides/search/searchWithRuleContexts.mustache index 329e8f45d4f..6182023b279 100644 --- a/templates/php/guides/search/searchWithRuleContexts.mustache +++ b/templates/php/guides/search/searchWithRuleContexts.mustache @@ -9,16 +9,12 @@ $getPlatformTag = function (): string { return ''; }; -try { - {{> snippets/init}} +{{> snippets/init}} - // get the buyer account information - $platformTag = $getPlatformTag(); - $searchParams = (new SearchParamsObject()) - ->setQuery('') - ->setRuleContexts([$platformTag]); +// get the buyer account information +$platformTag = $getPlatformTag(); +$searchParams = (new SearchParamsObject()) + ->setQuery('') + ->setRuleContexts([$platformTag]); - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} \ No newline at end of file +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}; diff --git a/templates/php/guides/search/setHeaderUserIDThenSaveObjects.mustache b/templates/php/guides/search/setHeaderUserIDThenSaveObjects.mustache index 03fff15faae..a6993b47328 100644 --- a/templates/php/guides/search/setHeaderUserIDThenSaveObjects.mustache +++ b/templates/php/guides/search/setHeaderUserIDThenSaveObjects.mustache @@ -5,13 +5,13 @@ require __DIR__.'/../vendor/autoload.php'; $playlists = [ /* Your records */ ]; -try { - {{> snippets/init}} +{{> snippets/init}} - foreach ($playlists as $playlist) { +foreach ($playlists as $playlist) { + try { $playlistUserID = $playlist['userID']; {{#dynamicSnippet}}saveObjectsPlaylistsWithRequestOptions{{/dynamicSnippet}}; + } catch (Exception $e) { + echo $e->getMessage() . PHP_EOL; } -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; } diff --git a/templates/php/guides/search/setSettingsThenSaveObjects.mustache b/templates/php/guides/search/setSettingsThenSaveObjects.mustache index fce4d4948a0..34e90bf49d9 100644 --- a/templates/php/guides/search/setSettingsThenSaveObjects.mustache +++ b/templates/php/guides/search/setSettingsThenSaveObjects.mustache @@ -14,10 +14,8 @@ $getIndexingApiKeyFor = function ($user) { return ""; // Implement your own logic here }; -try { - {{> snippets/init}} - - foreach ($playlists as $playlist) { +foreach ($playlists as $playlist) { + try { // Fetch from your own data storage and with your own code // the associated application ID and API key for this user $appID = $getAppIDFor($playlist['user']); @@ -32,7 +30,7 @@ try { {{#dynamicSnippet}}setSettings{{/dynamicSnippet}}; {{#dynamicSnippet}}saveObjectsPlaylists{{/dynamicSnippet}}; + } catch (Exception $e) { + echo $e->getMessage() . PHP_EOL; } -} catch (Exception $e) { - echo $e->getMessage() . PHP_EOL; -} \ No newline at end of file +} diff --git a/templates/php/guides/search/useConditionlessRule.mustache b/templates/php/guides/search/useConditionlessRule.mustache index 921a6233b5a..78171175b53 100644 --- a/templates/php/guides/search/useConditionlessRule.mustache +++ b/templates/php/guides/search/useConditionlessRule.mustache @@ -6,25 +6,21 @@ use Algolia\AlgoliaSearch\Model\Search\Consequence; use Algolia\AlgoliaSearch\Model\Search\Rule; use Algolia\AlgoliaSearch\Model\Search\TimeRange; -try { - {{> snippets/init}} +{{> snippets/init}} - $objectID = 'a-rule-id'; +$objectID = 'a-rule-id'; - $rule = (new Rule()) - ->setObjectID($objectID) - ->setConsequence(new Consequence(/* Set relevant consequence */)); +$rule = (new Rule()) + ->setObjectID($objectID) + ->setConsequence(new Consequence(/* Set relevant consequence */)); - // Set validity (optional) - $rule->setValidity( - [ - (new TimeRange()) - ->setFrom(1688774400) - ->setUntil(1738972800) - ] - ); +// Set validity (optional) +$rule->setValidity( + [ + (new TimeRange()) + ->setFrom(1688774400) + ->setUntil(1738972800) + ] +); - {{#dynamicSnippet}}saveRule{{/dynamicSnippet}}; -} catch (Exception $e) { - echo $e->getMessage().PHP_EOL; -} +{{#dynamicSnippet}}saveRule{{/dynamicSnippet}}; diff --git a/templates/python/config.mustache b/templates/python/config.mustache index b3ea68d096b..e7ce1502e0f 100644 --- a/templates/python/config.mustache +++ b/templates/python/config.mustache @@ -1,5 +1,5 @@ from os import environ -from typing import Optional +from typing import Dict, Optional from algoliasearch.http.hosts import ( CallType, diff --git a/templates/python/guides/ingestion/pushSetup.mustache b/templates/python/guides/ingestion/pushSetup.mustache index 2379c62a0ab..de01674bef3 100644 --- a/templates/python/guides/ingestion/pushSetup.mustache +++ b/templates/python/guides/ingestion/pushSetup.mustache @@ -2,14 +2,13 @@ import json {{> snippets/import}} -if __name__ == '__main__': - # use the region matching your applicationID - _{{> snippets/init}} +# use the region matching your applicationID +_{{> snippets/init}} - with open("records.json") as f: - records = json.load(f) +with open("records.json") as f: + records = json.load(f) - # setting `watch` to `true` will make the call synchronous - resp = {{#dynamicSnippet}}pushSetup{{/dynamicSnippet}} + # setting `watch` to `true` will make the call synchronous + resp = {{#dynamicSnippet}}pushSetup{{/dynamicSnippet}} - print(resp) + print(resp) diff --git a/templates/python/guides/search/deleteMultipleIndices.mustache b/templates/python/guides/search/deleteMultipleIndices.mustache index 871580f72e3..342a597c946 100644 --- a/templates/python/guides/search/deleteMultipleIndices.mustache +++ b/templates/python/guides/search/deleteMultipleIndices.mustache @@ -1,30 +1,24 @@ {{> snippets/import}} -if __name__ == "__main__": - try: - # You need an API key with `deleteIndex` - _{{> snippets/init}} - - # List all indices - indices = {{#dynamicSnippet}}listIndicesSimple{{/dynamicSnippet}} - - # Primary indices don't have a `primary` key - primary_indices = [index for index in indices.items if index.primary is None] - replica_indices = [index for index in indices.items if index.primary is not None] - - # Delete primary indices first - if primary_indices: - requests = [{"action": "delete", "indexName": index.name} for index in primary_indices] - {{#dynamicSnippet}}deleteMultipleIndicesPrimary{{/dynamicSnippet}} - print("Deleted primary indices.") - - # Now, delete replica indices - if replica_indices: - requests = [{"action": "delete", "indexName": index.name} for index in replica_indices] - {{#dynamicSnippet}}deleteMultipleIndicesReplica{{/dynamicSnippet}} - print("Deleted replica indices.\n") - - except Exception as e: - print(f"Error: {e}") - +# You need an API key with `deleteIndex` +_{{> snippets/init}} + +# List all indices +indices = {{#dynamicSnippet}}listIndicesSimple{{/dynamicSnippet}} + +# Primary indices don't have a `primary` key +primary_indices = [index for index in indices.items if index.primary is None] +replica_indices = [index for index in indices.items if index.primary is not None] + +# Delete primary indices first +if primary_indices: + requests = [{"action": "delete", "indexName": index.name} for index in primary_indices] + {{#dynamicSnippet}}deleteMultipleIndicesPrimary{{/dynamicSnippet}} + print("Deleted primary indices.") + +# Now, delete replica indices +if replica_indices: + requests = [{"action": "delete", "indexName": index.name} for index in replica_indices] + {{#dynamicSnippet}}deleteMultipleIndicesReplica{{/dynamicSnippet}} + print("Deleted replica indices.\n") diff --git a/templates/python/guides/search/enableFilterPromote.mustache b/templates/python/guides/search/enableFilterPromote.mustache index 2b16f2995a0..a96ac9ee7c4 100644 --- a/templates/python/guides/search/enableFilterPromote.mustache +++ b/templates/python/guides/search/enableFilterPromote.mustache @@ -4,19 +4,18 @@ from algoliasearch.search.models.consequence import Consequence from algoliasearch.search.models.rule import Rule -if __name__ == "__main__": - condition = Condition( - anchoring=Anchoring.IS, - pattern="{facet:brand}", - ) +condition = Condition( + anchoring=Anchoring.IS, + pattern="{facet:brand}", +) - consequence = Consequence( - filter_promotes=True, - ) +consequence = Consequence( + filter_promotes=True, +) - rule = Rule( - enabled=True, - object_id="rule_with_filterPromotes", - conditions=[condition], - consequence=consequence, - ) \ No newline at end of file +rule = Rule( + enabled=True, + object_id="rule_with_filterPromotes", + conditions=[condition], + consequence=consequence, +) \ No newline at end of file diff --git a/templates/python/guides/search/globalAlgoliaUserID.mustache b/templates/python/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..b94f8f36de2 --- /dev/null +++ b/templates/python/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,11 @@ +import datetime +import time + +{{> snippets/import}} +from algoliasearch.search.config import SearchConfig + + +_config = SearchConfig("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY") +_config.headers["x-algolia-userToken"] = "test-user-123" +_client = SearchClientSync.create_with_config(_config) +print(_client) \ No newline at end of file diff --git a/templates/python/guides/search/mcmSearchWithout.mustache b/templates/python/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..5098ae21786 --- /dev/null +++ b/templates/python/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,25 @@ +import datetime +import time + +{{> snippets/import}} + + +def _get_app_id_for(_user): + # Implement your own logic here + return "" + +def _get_indexing_api_key_for(_user): + # Implement your own logic here + return "" + +app_id = _get_app_id_for("user42") +api_key = _get_indexing_api_key_for("user42") + +_client = SearchClientSync(app_id, api_key) + +search_params = { + "query": "", + "facetFilters": ["user:user42", "user:public"] +} + +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/python/guides/search/saveImageClassifications.mustache b/templates/python/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..be637b8cc34 --- /dev/null +++ b/templates/python/guides/search/saveImageClassifications.mustache @@ -0,0 +1,21 @@ +{{> snippets/import}} +from algoliasearch.search.models.browse_response import BrowseResponse +from algoliasearch.search.models.index_settings import IndexSettings + +def _get_image_labels(image_url, object_id, score_limit): + # Implement your image classification logic here + return {"objectID": "", "imageURL": "", "objects": []} + +_{{> snippets/init}} + +records = [] + +def _aggregator(res: BrowseResponse): + for hit in res.hits: + props = hit.to_dict() + image_url = props['imageURL'] + records.append(_get_image_labels(image_url, hit.object_id, 0.5)) + +_client.browse_objects('', aggregator=_aggregator) + +{{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} \ No newline at end of file diff --git a/templates/python/guides/search/saveImageClassificationsAndSettings.mustache b/templates/python/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..aa3baef4799 --- /dev/null +++ b/templates/python/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,43 @@ +{{> snippets/import}} +from algoliasearch.search.models.browse_response import BrowseResponse +from algoliasearch.search.models.index_settings import IndexSettings + +def _get_image_labels(image_url, object_id, score_limit): + # Implement your image classification logic here + return {"objectID": "", "imageURL": "", "objects": []} + +_{{> snippets/init}} + +records = [] + +def _aggregator(res: BrowseResponse): + for hit in res.hits: + props = hit.to_dict() + image_url = props['imageURL'] + records.append(_get_image_labels(image_url, hit.object_id, 0.5)) + +_client.browse_objects('', aggregator=_aggregator) + +{{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} + +facets = [] +attributes = [] + +for record in records: + for obj in record["objects"]: + for key, values in obj.items(): + if isinstance(values, list): + facets.extend([ + f"searchable(objects.{key}.label)", + f"searchable(objects.{key}.score)" + ]) + attributes.append(f"objects.{key}.label)") + +current_settings = {{#dynamicSnippet}}getSettings{{/dynamicSnippet}} + +settings = IndexSettings( + searchable_attributes=(current_settings.searchable_attributes or []) + attributes, + attributes_for_faceting=(current_settings.attributes_for_faceting or []) + facets +) + +{{#dynamicSnippet}}setSettings{{/dynamicSnippet}} \ No newline at end of file diff --git a/templates/python/guides/search/saveObjectsChunks.mustache b/templates/python/guides/search/saveObjectsChunks.mustache index 8c2b2a573e8..410f7418ef3 100644 --- a/templates/python/guides/search/saveObjectsChunks.mustache +++ b/templates/python/guides/search/saveObjectsChunks.mustache @@ -3,19 +3,16 @@ import json {{> snippets/import}} -if __name__ == "__main__": - try: - _{{> snippets/init}} +with open("records.json", "r", encoding="utf-8") as f: + records = json.load(f) - with open("records.json", "r", encoding="utf-8") as f: - records = json.load(f) + _{{> snippets/init}} - chunk_size = 10000 - - for begin_index in range(0, len(records), chunk_size): - chunk = records[begin_index:begin_index + chunk_size] - {{#dynamicSnippet}}saveObjectsChunks{{/dynamicSnippet}} - - except Exception as e: - print(f"Error: {e}") + chunk_size = 10000 + for begin_index in range(0, len(records), chunk_size): + try: + chunk = records[begin_index:begin_index + chunk_size] + {{#dynamicSnippet}}saveObjectsChunks{{/dynamicSnippet}} + except Exception as e: + print(f"Error: {e}") diff --git a/templates/python/guides/search/saveObjectsMCM.mustache b/templates/python/guides/search/saveObjectsMCM.mustache index 59255d698aa..2bae936ee07 100644 --- a/templates/python/guides/search/saveObjectsMCM.mustache +++ b/templates/python/guides/search/saveObjectsMCM.mustache @@ -3,17 +3,16 @@ def _get_all_app_id_configurations(): return [] # A list of your MCM AppID/ApiKey pairs -if __name__ == "__main__": - playlists = [] # Your records +playlists = [] # Your records - # Fetch from your own data storage and with your own code - # the list of application IDs and API keys to target each cluster - configurations = _get_all_app_id_configurations() +# Fetch from your own data storage and with your own code +# the list of application IDs and API keys to target each cluster +configurations = _get_all_app_id_configurations() - # Send the records to each cluster - for appID, apiKey in configurations: - try: - _client = SearchClientSync(appID, apiKey) - {{#dynamicSnippet}}saveObjectsPlaylists{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") +# Send the records to each cluster +for appID, apiKey in configurations: + try: + _client = SearchClientSync(appID, apiKey) + {{#dynamicSnippet}}saveObjectsPlaylists{{/dynamicSnippet}} + except Exception as e: + print(f"Error: {e}") diff --git a/templates/python/guides/search/saveObjectsModified.mustache b/templates/python/guides/search/saveObjectsModified.mustache index a0a016cfc77..3bec30322a6 100644 --- a/templates/python/guides/search/saveObjectsModified.mustache +++ b/templates/python/guides/search/saveObjectsModified.mustache @@ -3,27 +3,23 @@ import json {{> snippets/import}} -if __name__ == "__main__": - try: - _{{> snippets/init}} +with open("products.json", "r", encoding="utf-8") as f: + products = json.load(f) - with open("products.json", "r", encoding="utf-8") as f: - products = json.load(f) + _{{> snippets/init}} - records = [] + records = [] - for product in products: - reference = product["product_reference"] + for product in products: + reference = product["product_reference"] - suffixes = [] - while len(reference) > 1: - reference = reference[1:] - suffixes.append(reference) + suffixes = [] + while len(reference) > 1: + reference = reference[1:] + suffixes.append(reference) - product["product_reference_suffixes"] = suffixes - records.append(product) + product["product_reference_suffixes"] = suffixes + records.append(product) - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") + {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} diff --git a/templates/python/guides/search/saveObjectsMovies.mustache b/templates/python/guides/search/saveObjectsMovies.mustache index 61e88cb5f4a..0180a0df645 100644 --- a/templates/python/guides/search/saveObjectsMovies.mustache +++ b/templates/python/guides/search/saveObjectsMovies.mustache @@ -2,13 +2,12 @@ import requests {{> snippets/import}} -if __name__ == "__main__": - # Fetch sample dataset - url = "https://dashboard.algolia.com/api/1/sample_datasets?type=movie" - movies = requests.get(url).json() +# Fetch sample dataset +url = "https://dashboard.algolia.com/api/1/sample_datasets?type=movie" +movies = requests.get(url).json() - # Connect and authenticate with your Algolia app - _{{> snippets/init}} +# Connect and authenticate with your Algolia app +_{{> snippets/init}} - # Save records in Algolia index - {{#dynamicSnippet}}saveObjectsMovies{{/dynamicSnippet}} +# Save records in Algolia index +{{#dynamicSnippet}}saveObjectsMovies{{/dynamicSnippet}} diff --git a/templates/python/guides/search/saveObjectsPublicUser.mustache b/templates/python/guides/search/saveObjectsPublicUser.mustache index cac84f3186e..6b894320c6b 100644 --- a/templates/python/guides/search/saveObjectsPublicUser.mustache +++ b/templates/python/guides/search/saveObjectsPublicUser.mustache @@ -1,12 +1,8 @@ {{> snippets/import}} -if __name__ == "__main__": - playlists = [] # Your records +playlists = [] # Your records - try: - _{{> snippets/init}} +_{{> snippets/init}} - {{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") +{{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}} diff --git a/templates/python/guides/search/savePopularRecords.mustache b/templates/python/guides/search/savePopularRecords.mustache index dbecb23702a..8fd7696c917 100644 --- a/templates/python/guides/search/savePopularRecords.mustache +++ b/templates/python/guides/search/savePopularRecords.mustache @@ -2,25 +2,21 @@ from algoliasearch.search.models.browse_response import BrowseResponse -if __name__ == "__main__": - try: - _{{> snippets/init}} +_{{> snippets/init}} - records = [] - def _aggregator(resp: BrowseResponse): - for hit in resp.hits: - hit_dict = hit.to_dict() - records.append({ - "twitterHandle": hit_dict["twitterHandle"], - "nbFollowers": hit_dict["nbFollowers"], - "isPopular": hit_dict["nbFollowers"] > 1000000, - }) +records = [] +def _aggregator(resp: BrowseResponse): + for hit in resp.hits: + hit_dict = hit.to_dict() + records.append({ + "twitterHandle": hit_dict["twitterHandle"], + "nbFollowers": hit_dict["nbFollowers"], + "isPopular": hit_dict["nbFollowers"] > 1000000, + }) - _client.browse_objects( - index_name="", - aggregator=_aggregator, - ) +_client.browse_objects( + index_name="", + aggregator=_aggregator, +) - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") +{{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} diff --git a/templates/python/guides/search/searchFuturePublishedBooks.mustache b/templates/python/guides/search/searchFuturePublishedBooks.mustache index 20ac0c8b551..8b869bc2eaa 100644 --- a/templates/python/guides/search/searchFuturePublishedBooks.mustache +++ b/templates/python/guides/search/searchFuturePublishedBooks.mustache @@ -3,16 +3,12 @@ import time {{> snippets/import}} -if __name__ == "__main__": - try: - _{{> snippets/init}} +_{{> snippets/init}} - date_timestamp = time.time() # Get current timestamp - search_params = { - "query": "", - "filters": f"date_timestamp > {date_timestamp}" - } +date_timestamp = time.time() # Get current timestamp +search_params = { + "query": "", + "filters": f"date_timestamp > {date_timestamp}" +} - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/python/guides/search/searchInReplicaIndex.mustache b/templates/python/guides/search/searchInReplicaIndex.mustache index 28ed1612142..a8889e22715 100644 --- a/templates/python/guides/search/searchInReplicaIndex.mustache +++ b/templates/python/guides/search/searchInReplicaIndex.mustache @@ -1,16 +1,15 @@ {{> snippets/import}} -if __name__ == "__main__": - _{{> snippets/init}} +_{{> snippets/init}} - query = "query" +query = "query" - # 1. Change the sort dynamically based on the UI events - sort_by_price = False +# 1. Change the sort dynamically based on the UI events +sort_by_price = False - # 2. Get the index name based on sortByPrice - index_name = "products_price_desc" if sort_by_price else "products" +# 2. Get the index name based on sortByPrice +index_name = "products_price_desc" if sort_by_price else "products" - # 3. Search on dynamic index name (primary or replica) - {{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}} +# 3. Search on dynamic index name (primary or replica) +{{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}} diff --git a/templates/python/guides/search/searchRecentlyPublishedBooks.mustache b/templates/python/guides/search/searchRecentlyPublishedBooks.mustache index 1748bda0a14..94ce4105373 100644 --- a/templates/python/guides/search/searchRecentlyPublishedBooks.mustache +++ b/templates/python/guides/search/searchRecentlyPublishedBooks.mustache @@ -4,17 +4,13 @@ import time {{> snippets/import}} -if __name__ == "__main__": - try: - _{{> snippets/init}} +_{{> snippets/init}} - date = datetime.datetime.now() - datetime.timedelta(days=365) - date_timestamp = int(time.mktime(date.timetuple())) - search_params = { - "query": "", - "filters": f"date_timestamp > {date_timestamp}" - } +date = datetime.datetime.now() - datetime.timedelta(days=365) +date_timestamp = int(time.mktime(date.timetuple())) +search_params = { + "query": "", + "filters": f"date_timestamp > {date_timestamp}" +} - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/python/guides/search/searchWithAnalyticsAndHeader.mustache b/templates/python/guides/search/searchWithAnalyticsAndHeader.mustache index c3d12f1ba93..1c4c6816cf3 100644 --- a/templates/python/guides/search/searchWithAnalyticsAndHeader.mustache +++ b/templates/python/guides/search/searchWithAnalyticsAndHeader.mustache @@ -2,20 +2,18 @@ from algoliasearch.search.models.search_params import SearchParams -if __name__ == "__main__": - _{{> snippets/init}} +_{{> snippets/init}} - """ - '94.228.178.246' should be replaced with your user's IP address. - Depending on your stack there are multiple ways to get this information. - """ - ip = "94.228.178.246" - query = "query" +""" +'94.228.178.246' should be replaced with your user's IP address. +Depending on your stack there are multiple ways to get this information. +""" +ip = "94.228.178.246" +query = "query" - search_params = SearchParams( - query=query, - analytics=True, - ) - - {{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}} +search_params = SearchParams( + query=query, + analytics=True, +) +{{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}} diff --git a/templates/python/guides/search/searchWithGAToken.mustache b/templates/python/guides/search/searchWithGAToken.mustache index bc549aa5481..c2d0c360917 100644 --- a/templates/python/guides/search/searchWithGAToken.mustache +++ b/templates/python/guides/search/searchWithGAToken.mustache @@ -5,22 +5,21 @@ def _get_google_analytics_user_id_from_browser_cookie(cookie_name: str) -> str: # Implement your logic here return "" -if __name__ == "__main__": - try: - _{{> snippets/init}} +try: + _{{> snippets/init}} - user_token = _get_google_analytics_user_id_from_browser_cookie("_ga") - search_params = { - "query": "", - "userToken": user_token, - } + user_token = _get_google_analytics_user_id_from_browser_cookie("_ga") + search_params = { + "query": "", + "userToken": user_token, + } - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - logged_in_user = None + logged_in_user = None - search_params["user_token"] = logged_in_user or user_token + search_params["user_token"] = logged_in_user or user_token - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} +except Exception as e: + print(f"Error: {e}") diff --git a/templates/python/guides/search/searchWithLogicalOr.mustache b/templates/python/guides/search/searchWithLogicalOr.mustache index 7ff865334d7..77c547c7d50 100644 --- a/templates/python/guides/search/searchWithLogicalOr.mustache +++ b/templates/python/guides/search/searchWithLogicalOr.mustache @@ -2,13 +2,13 @@ from algoliasearch.search.models.search_params import SearchParams -if __name__ == "__main__": - _{{> snippets/init}} - - query = "the query" - optional_words = ["the", "query"] - search_params = SearchParams( - query=query, - optional_words=optional_words, - ) - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} +_{{> snippets/init}} + +query = "the query" +optional_words = ["the", "query"] +search_params = SearchParams( + query=query, + optional_words=optional_words, +) + +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/python/guides/search/searchWithOptionalFilters.mustache b/templates/python/guides/search/searchWithOptionalFilters.mustache index 71ed2149a67..04f4e41f794 100644 --- a/templates/python/guides/search/searchWithOptionalFilters.mustache +++ b/templates/python/guides/search/searchWithOptionalFilters.mustache @@ -6,18 +6,14 @@ def _reduce_labels_to_filters(_labels): # Implement your logic here return [] -if __name__ == "__main__": - labels = [] # A list of labels +labels = [] # A list of labels - try: - _{{> snippets/init}} +_{{> snippets/init}} - optional_filters = _reduce_labels_to_filters(labels) - search_params = SearchParams( - query="", - optional_filters=optional_filters, - ) +optional_filters = _reduce_labels_to_filters(labels) +search_params = SearchParams( + query="", + optional_filters=optional_filters, +) - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/python/guides/search/searchWithRuleContextBuyer.mustache b/templates/python/guides/search/searchWithRuleContextBuyer.mustache index c9dc5d96aaa..6326327dd9a 100644 --- a/templates/python/guides/search/searchWithRuleContextBuyer.mustache +++ b/templates/python/guides/search/searchWithRuleContextBuyer.mustache @@ -6,18 +6,13 @@ def _get_buyer_account_id() -> str: # Implement your logic here return "" -if __name__ == "__main__": +_{{> snippets/init}} - try: - _{{> snippets/init}} +# get the buyer account information +buyer = _get_buyer_account_id() +search_params = SearchParams( + query="", + rule_contexts=[buyer], +) - # get the buyer account information - buyer = _get_buyer_account_id() - search_params = SearchParams( - query="", - rule_contexts=[buyer], - ) - - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/python/guides/search/searchWithRuleContexts.mustache b/templates/python/guides/search/searchWithRuleContexts.mustache index 0aa4a48d51d..929b68a8bb9 100644 --- a/templates/python/guides/search/searchWithRuleContexts.mustache +++ b/templates/python/guides/search/searchWithRuleContexts.mustache @@ -6,17 +6,13 @@ def _get_platform_tag() -> str: # Implement your logic here return "" -if __name__ == "__main__": - try: - _{{> snippets/init}} +_{{> snippets/init}} - # get the buyer account information - platform_tag = _get_platform_tag() - search_params = SearchParams( - query="", - rule_contexts=[platform_tag], - ) +# get the buyer account information +platform_tag = _get_platform_tag() +search_params = SearchParams( + query="", + rule_contexts=[platform_tag], +) - {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - except Exception as e: - print(f"Error: {e}") +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/python/guides/search/setHeaderUserIDThenSaveObjects.mustache b/templates/python/guides/search/setHeaderUserIDThenSaveObjects.mustache index 15e97e50981..bd67cbc6483 100644 --- a/templates/python/guides/search/setHeaderUserIDThenSaveObjects.mustache +++ b/templates/python/guides/search/setHeaderUserIDThenSaveObjects.mustache @@ -1,14 +1,13 @@ {{> snippets/import}} -if __name__ == "__main__": - playlists = [] # Your records +playlists = [] # Your records - try: - _{{> snippets/init}} +_{{> snippets/init}} - for playlist in playlists: - playlist_user_id = playlist["userID"] - {{#dynamicSnippet}}saveObjectsPlaylistsWithRequestOptions{{/dynamicSnippet}} +for playlist in playlists: + try: + playlist_user_id = playlist["userID"] + {{#dynamicSnippet}}saveObjectsPlaylistsWithRequestOptions{{/dynamicSnippet}} except Exception as e: print(f"Error: {e}") diff --git a/templates/python/guides/search/setSettingsThenSaveObjects.mustache b/templates/python/guides/search/setSettingsThenSaveObjects.mustache index e5b85c564b8..a346ab7e813 100644 --- a/templates/python/guides/search/setSettingsThenSaveObjects.mustache +++ b/templates/python/guides/search/setSettingsThenSaveObjects.mustache @@ -10,20 +10,19 @@ def _get_indexing_api_key_for(_user): # Implement your own logic here return "" -if __name__ == "__main__": - playlists = [] # Your records +playlists = [] # Your records - try: - for playlist in playlists: - app_id = _get_app_id_for(playlist["user"]) - api_key = _get_indexing_api_key_for(playlist["user"]) +for playlist in playlists: + app_id = _get_app_id_for(playlist["user"]) + api_key = _get_indexing_api_key_for(playlist["user"]) - _client = SearchClientSync(app_id, api_key) - settings = IndexSettings( - attributes_for_faceting=["filterOnly(user)"] - ) - {{#dynamicSnippet}}setSettings{{/dynamicSnippet}} + _client = SearchClientSync(app_id, api_key) + settings = IndexSettings( + attributes_for_faceting=["filterOnly(user)"] + ) + try: + {{#dynamicSnippet}}setSettings{{/dynamicSnippet}} - {{#dynamicSnippet}}saveObjectsPlaylists{{/dynamicSnippet}} + {{#dynamicSnippet}}saveObjectsPlaylists{{/dynamicSnippet}} except Exception as e: print(f"Error: {e}") diff --git a/templates/python/guides/search/useConditionlessRule.mustache b/templates/python/guides/search/useConditionlessRule.mustache index ebbcf862f88..49f635e8339 100644 --- a/templates/python/guides/search/useConditionlessRule.mustache +++ b/templates/python/guides/search/useConditionlessRule.mustache @@ -3,24 +3,23 @@ from algoliasearch.search.models.consequence import Consequence from algoliasearch.search.models.rule import Rule from algoliasearch.search.models.time_range import TimeRange -if __name__ == "__main__": - _{{> snippets/init}} +_{{> snippets/init}} - object_id = "a-rule-id" +object_id = "a-rule-id" - rule = Rule( - object_id=object_id, - consequence=Consequence( - # Set relevant consequence - ), - ) +rule = Rule( + object_id=object_id, + consequence=Consequence( + # Set relevant consequence + ), +) - # Set validity (optional) - rule.validity = [ - TimeRange( - var_from=1688774400, - until=1738972800, - ), - ] +# Set validity (optional) +rule.validity = [ + TimeRange( + var_from=1688774400, + until=1738972800, + ), +] - {{#dynamicSnippet}}saveRule{{/dynamicSnippet}} +{{#dynamicSnippet}}saveRule{{/dynamicSnippet}} diff --git a/templates/ruby/guides/search/globalAlgoliaUserID.mustache b/templates/ruby/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..383cf0c7dbd --- /dev/null +++ b/templates/ruby/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,7 @@ +import time + +{{> snippets/import}} + +client = Algolia::SearchClient.create(app_id, api_key) +client.api_client.config.header_params["X-Algolia-UserToken"] = "test-user-123" +puts(client.api_client.config.header_params) \ No newline at end of file diff --git a/templates/ruby/guides/search/mcmSearchWithout.mustache b/templates/ruby/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..3799930098f --- /dev/null +++ b/templates/ruby/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,25 @@ +import time + +{{> snippets/import}} + +def get_app_id_for(_user) + # Implement your own logic here + "" +end + +def get_indexing_api_key_for(_user) + # Implement your own logic here + "" +end + +app_id = get_app_id_for("user42") +api_key = get_indexing_api_key_for("user42") + +client = Algolia::SearchClient.create(app_id, api_key) + +search_params = Algolia::Search::SearchParamsObject.new( + query: "", + facet_filters: %w[user:user42 user:public] +) + +{{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} diff --git a/templates/ruby/guides/search/saveImageClassifications.mustache b/templates/ruby/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..01c91d65b65 --- /dev/null +++ b/templates/ruby/guides/search/saveImageClassifications.mustache @@ -0,0 +1,21 @@ +{{> snippets/import}} + +def get_image_labels(image_url, object_id, score_limit) + # Implement your image classification logic here + {"objectID" => "", "imageURL" => "", "objects" => []} +end + +{{> snippets/init}} + +records = [] + +client.browse_objects( + '', +) do |resp| + resp.hits.each do |hit| + image_url = hit['imageURL'] + records << get_image_labels(image_url, hit['objectID'], 0.5) + end +end + +{{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} \ No newline at end of file diff --git a/templates/ruby/guides/search/saveImageClassificationsAndSettings.mustache b/templates/ruby/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..58ee91a4eca --- /dev/null +++ b/templates/ruby/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,47 @@ +{{> snippets/import}} + +def get_image_labels(image_url, object_id, score_limit) + # Implement your image classification logic here + {"objectID" => "", "imageURL" => "", "objects" => []} +end + +{{> snippets/init}} + +records = [] + +client.browse_objects( + '', +) do |resp| + resp.hits.each do |hit| + image_url = hit['imageURL'] + records << get_image_labels(image_url, hit['objectID'], 0.5) + end +end + +{{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} + +facets = [] +attributes = [] + +records.each do |record| + record["objects"].each do |obj| + obj.each do |key, values| + if values.is_a?(Array) + facets.push( + "searchable(objects.#{key}.label)", + "searchable(objects.#{key}.score)" + ) + attributes << "objects.#{key}.label)" + end + end + end +end + +current_settings = {{#dynamicSnippet}}getSettings{{/dynamicSnippet}} + +settings = Algolia::Search::IndexSettings.new( + searchable_attributes: (current_settings.searchable_attributes || []) + attributes, + attributes_for_faceting: (current_settings.attributes_for_faceting || []) + facets +) + +{{#dynamicSnippet}}setSettings{{/dynamicSnippet}} \ No newline at end of file diff --git a/templates/scala/guides/search/globalAlgoliaUserID.mustache b/templates/scala/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..ff01373cd73 --- /dev/null +++ b/templates/scala/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,12 @@ +{{> snippets/import}} + +def globalAlgoliaUserID(): Unit = { + val client = SearchClient( + appId = "ALGOLIA_APPLICATION_ID", + apiKey = "ALGOLIA_API_KEY", + clientOptions = ClientOptions( + defaultHeaders = Map("X-Algolia-UserToken" -> "test-user-123") + ) + ) + println(client) +} diff --git a/templates/scala/guides/search/mcmSearchWithout.mustache b/templates/scala/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..cae06306dd2 --- /dev/null +++ b/templates/scala/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,41 @@ +import scala.concurrent.Future +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Await +import scala.concurrent.duration.Duration + +{{> snippets/import}} +import algoliasearch.search.{FacetFilters, SearchParamsObject} + +def mcmSearchWithout(): Future[Unit] = { + val getAppIDFor: String => String = _ => { + "" // Implement your own logic here + } + val getIndexingApiKeyFor: String => String = _ => { + "" // Implement your own logic here + } + + // Fetch from your own data storage and with your own code + // the associated application ID and API key for this user + val appID = getAppIDFor("user42") + val apiKey = getIndexingApiKeyFor("user42") + + val client = SearchClient(appID, apiKey) + val searchParams = SearchParamsObject( + query = Some(""), + facetFilters = Some( + FacetFilters.SeqOfFacetFilters( + Seq( + FacetFilters.StringValue("user:user42"), + FacetFilters.StringValue("user:public") + ) + ) + ) + ) + + {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}}.map { response => + println(response) + }.recover { + case ex: Exception => + println(s"An error occurred: ${ex.getMessage}") + } +} diff --git a/templates/scala/guides/search/saveImageClassifications.mustache b/templates/scala/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..73ee4fcf9ee --- /dev/null +++ b/templates/scala/guides/search/saveImageClassifications.mustache @@ -0,0 +1,45 @@ +import scala.concurrent.Future +import scala.concurrent.ExecutionContext.Implicits.global + +{{> snippets/import}} +import algoliasearch.search.BrowseParamsObject + +class Image( + val imageURL: String, + val objectID: String, + val objects: Seq[Map[String, Any]] +) + +def saveImageClassifications(): Future[Unit] = { + // Retrieve labels + def getImageLabels(imageURL: String, objectID: String, scoreLimit: Float): Image = { + // Implement your image classification logic here + Image(imageURL, objectID, Seq()) + } + + // API key ACL should include editSettings / addObject + {{> snippets/init}} + + val records: Seq[Image] = Seq.empty + + client.browseObjects( + indexName = "", + browseParams = BrowseParamsObject(), + aggregator = { browseResponse => + records.appendedAll( + browseResponse.hits.map { hit => + val props = hit.additionalProperties.getOrElse(List()).toMap + getImageLabels(props.get("imageURL").toString, hit.objectID, 0.5f) + }, + ) + }, + ) + + // Update records with image classifications + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}}.map { response => + println(response) + }.recover { + case ex: Exception => + println(s"An error occurred: ${ex.getMessage}") + } +} diff --git a/templates/scala/guides/search/saveImageClassificationsAndSettings.mustache b/templates/scala/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..eea73b3826a --- /dev/null +++ b/templates/scala/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,67 @@ +import scala.concurrent.{Await, Future} +import scala.concurrent.duration.Duration +import scala.concurrent.ExecutionContext.Implicits.global + +{{> snippets/import}} +import algoliasearch.search.{BrowseParamsObject, IndexSettings} + +def saveImageClassificationsAndSettings(): Future[Unit] = { + // Retrieve labels + def getImageLabels(imageURL: String, objectID: String, scoreLimit: Float): Image = { + // Implement your image classification logic here + Image(imageURL, objectID, Seq()) + } + + // API key ACL should include editSettings / addObject + {{> snippets/init}} + + var records: Seq[Image] = Seq.empty + + client.browseObjects( + indexName = "", + browseParams = BrowseParamsObject(), + aggregator = { browseResponse => + records = records.appendedAll( + browseResponse.hits.map { hit => + val props = hit.additionalProperties.getOrElse(List()).toMap + getImageLabels(props.get("imageURL").toString, hit.objectID, 0.5f) + }, + ) + }, + ) + + // Update records with image classifications + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} + + var facets: Seq[String] = Seq.empty + var attributes: Seq[String] = Seq.empty + + records.foreach(record => { + record.objects.foreach(obj => { + obj.foreach { case (key, value) => + if (value.isInstanceOf[scala.collection.Iterable[?]]) { + facets = facets.appended(s"searchable(objects.${key}.label)") + facets = facets.appended(s"searchable(objects.${key}.score)") + attributes = attributes.appended(s"objects.${key}.label") + } + } + }) + }) + + val currentSettings = Await.result( + {{#dynamicSnippet}}getSettings{{/dynamicSnippet}}, + Duration(5, "sec") + ) + + val settings = IndexSettings( + attributesForFaceting = Some(currentSettings.attributesForFaceting.getOrElse(Seq.empty) ++ facets), + searchableAttributes = Some(currentSettings.searchableAttributes.getOrElse(Seq.empty) ++ attributes) + ) + + {{#dynamicSnippet}}setSettings{{/dynamicSnippet}}.map { response => + println(response) + }.recover { + case ex: Exception => + println(s"An error occurred: ${ex.getMessage}") + } +} diff --git a/templates/scala/guides/search/savePopularRecords.mustache b/templates/scala/guides/search/savePopularRecords.mustache index 3091c8b8320..cf231136b53 100644 --- a/templates/scala/guides/search/savePopularRecords.mustache +++ b/templates/scala/guides/search/savePopularRecords.mustache @@ -20,7 +20,7 @@ def savePopularRecords(): Future[Unit] = { records = records ++ response.hits.map { hit => val props = hit.additionalProperties.getOrElse(List()).toMap - val nbFollowers = props("nbFollowers").toString.toInt + var nbFollowers = props("nbFollowers").toString.toInt Record( twitterHandle = props("twitterHandle").toString, diff --git a/templates/swift/guides/search/enableFilterPromote.mustache b/templates/swift/guides/search/enableFilterPromote.mustache index 3e4d64e7fe6..5d7eef0c496 100644 --- a/templates/swift/guides/search/enableFilterPromote.mustache +++ b/templates/swift/guides/search/enableFilterPromote.mustache @@ -17,4 +17,5 @@ func enableFilterPromote() async throws { ) let rule = Rule(objectID: "rule_with_filterPromotes", conditions: [condition], consequence: consequence) + print(rule) } \ No newline at end of file diff --git a/templates/swift/guides/search/globalAlgoliaUserID.mustache b/templates/swift/guides/search/globalAlgoliaUserID.mustache new file mode 100644 index 00000000000..eabbc4679e2 --- /dev/null +++ b/templates/swift/guides/search/globalAlgoliaUserID.mustache @@ -0,0 +1,17 @@ +import Foundation +#if os(Linux) // For linux interop + import FoundationNetworking +#endif + +import Core +{{> snippets/import}} + +func globalAlgoliaUserID() async throws { + let configuration = try SearchClientConfiguration( + appID: "ALGOLIA_APPLICATION_ID", + apiKey: "ALGOLIA_API_KEY", + defaultHeaders: ["X-Algolia-UserToken": "test-user-123"] + ) + let client = SearchClient(configuration: configuration) + print(client) +} \ No newline at end of file diff --git a/templates/swift/guides/search/mcmSearchWithout.mustache b/templates/swift/guides/search/mcmSearchWithout.mustache new file mode 100644 index 00000000000..84d74c9ebe5 --- /dev/null +++ b/templates/swift/guides/search/mcmSearchWithout.mustache @@ -0,0 +1,28 @@ +import Foundation +#if os(Linux) // For linux interop + import FoundationNetworking +#endif + +import Core +{{> snippets/import}} + +func mcmSearchWithout() async throws { + let getAppIDFor = {(_: String) in ""} // Implement your own logic here + let getIndexingApiKeyFor = {(_: String) in ""} // Implement your own logic here + + // Fetch from your own data storage and with your own code + // the associated application ID and API key for this user + let appID = getAppIDFor("user42"); + let apiKey = getIndexingApiKeyFor("user42"); + + let client = try SearchClient(appID: appID, apiKey: apiKey) + let searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject( + query: "", + facetFilters: .arrayOfSearchFacetFilters([.string("user:user42"), .string("user:public")]) + ) + ) + + let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + print(response) +} \ No newline at end of file diff --git a/templates/swift/guides/search/saveImageClassifications.mustache b/templates/swift/guides/search/saveImageClassifications.mustache new file mode 100644 index 00000000000..f7f22157a0a --- /dev/null +++ b/templates/swift/guides/search/saveImageClassifications.mustache @@ -0,0 +1,37 @@ +import Foundation +#if os(Linux) // For linux interop + import FoundationNetworking +#endif + +import Core +{{> snippets/import}} + +func saveImageClassifications() async throws { + struct Image: Codable { + var objectID: String + var imageURL: String + var objects: [[String: AnyCodable]] + } + + func getImageLabels(imageURL _: String, objectID _: String, scoreLimit _: Double) -> Image { + // Implement your image classification logic here + Image(objectID: "", imageURL: "", objects: []) + } + + {{> snippets/init}} + + var records: [Image] = [] + + try await client.browseObjects( + indexName: "", + browseParams: BrowseParamsObject(), + aggregator: { (response: BrowseResponse) in + records.append(contentsOf: response.hits.map { hit in + let imageURL = hit.imageURL + return getImageLabels(imageURL: imageURL, objectID: hit.objectID, scoreLimit: 0.5) + }) + } + ) + + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} +} \ No newline at end of file diff --git a/templates/swift/guides/search/saveImageClassificationsAndSettings.mustache b/templates/swift/guides/search/saveImageClassificationsAndSettings.mustache new file mode 100644 index 00000000000..9c0b87f51f2 --- /dev/null +++ b/templates/swift/guides/search/saveImageClassificationsAndSettings.mustache @@ -0,0 +1,63 @@ +import Foundation +#if os(Linux) // For linux interop + import FoundationNetworking +#endif + +import Core +{{> snippets/import}} + +func saveImageClassificationsAndSettings() async throws { + struct Image: Codable { + var objectID: String + var imageURL: String + var objects: [[String: AnyCodable]] + } + + func getImageLabels(imageURL _: String, objectID _: String, scoreLimit _: Double) -> Image { + // Implement your image classification logic here + Image(objectID: "", imageURL: "", objects: []) + } + + {{> snippets/init}} + + var records: [Image] = [] + + try await client.browseObjects( + indexName: "", + browseParams: BrowseParamsObject(), + aggregator: { (response: BrowseResponse) in + records.append(contentsOf: response.hits.map { hit in + let imageURL = hit.imageURL + return getImageLabels(imageURL: imageURL, objectID: hit.objectID, scoreLimit: 0.5) + }) + } + ) + + {{#dynamicSnippet}}partialUpdatesRecords{{/dynamicSnippet}} + + var facets: [String] = [] + var attributes: [String] = [] + + for record in records { + for obj in record.objects { + for (key, values) in obj { + if values.value is [Any] { + facets.append(contentsOf: [ + "searchable(objects.\(key).label)", + "searchable(objects.\(key).score)", + ]) + attributes.append("objects.\(key).label)") + } + } + } + } + + let currentSettings = {{#dynamicSnippet}}getSettings{{/dynamicSnippet}} + + let settings = IndexSettings( + attributesForFaceting: (currentSettings.attributesForFaceting ?? []) + facets, + searchableAttributes: (currentSettings.searchableAttributes ?? []) + attributes + ) + + {{#dynamicSnippet}}setSettings{{/dynamicSnippet}} +} \ No newline at end of file diff --git a/templates/swift/guides/search/saveObjectsChunks.mustache b/templates/swift/guides/search/saveObjectsChunks.mustache index f251d740f3d..6dc2d82fb72 100644 --- a/templates/swift/guides/search/saveObjectsChunks.mustache +++ b/templates/swift/guides/search/saveObjectsChunks.mustache @@ -7,22 +7,18 @@ import Core {{> snippets/import}} func saveObjectsChunks() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - let path = URL(string: #file)!.deletingLastPathComponent() - .appendingPathComponent("actors.json") - let data = try Data(contentsOf: URL(fileURLWithPath: path.absoluteString)) - let records = try JSONDecoder().decode([AnyCodable].self, from: data) + let path = URL(string: #file)!.deletingLastPathComponent() + .appendingPathComponent("actors.json") + let data = try Data(contentsOf: URL(fileURLWithPath: path.absoluteString)) + let records = try JSONDecoder().decode([AnyCodable].self, from: data) - let chunkSize = 10000 + let chunkSize = 10000 - for beginIndex in stride(from: 0, to: records.count, by: chunkSize) { - let endIndex = min(beginIndex + chunkSize, records.count) - let chunk = Array(records[beginIndex.. snippets/import}} func saveObjectsModified() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - let path = URL(string: #file)!.deletingLastPathComponent() - .appendingPathComponent("products.json") - let data = try Data(contentsOf: URL(fileURLWithPath: path.absoluteString)) - let products = try JSONDecoder().decode([[String: AnyCodable]].self, from: data) + let path = URL(string: #file)!.deletingLastPathComponent() + .appendingPathComponent("products.json") + let data = try Data(contentsOf: URL(fileURLWithPath: path.absoluteString)) + let products = try JSONDecoder().decode([[String: AnyCodable]].self, from: data) - let records = products.map { (product) -> [String: AnyCodable] in - var reference = product["product_reference"]?.value as! String - var suffixes: [String] = [] + let records = products.map { (product) -> [String: AnyCodable] in + var reference = product["product_reference"]?.value as! String + var suffixes: [String] = [] - while reference.count > 1 { - reference = String(reference.dropFirst()) - suffixes.append(reference) - } - var record: [String: AnyCodable] = product - record["product_reference_suffixes"] = AnyCodable(suffixes) - return record - } - - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} - } catch { - print(error) + while reference.count > 1 { + reference = String(reference.dropFirst()) + suffixes.append(reference) + } + var record: [String: AnyCodable] = product + record["product_reference_suffixes"] = AnyCodable(suffixes) + return record } + + {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} } \ No newline at end of file diff --git a/templates/swift/guides/search/saveObjectsPublicUser.mustache b/templates/swift/guides/search/saveObjectsPublicUser.mustache index 7e9e98b5dd5..63484f07d04 100644 --- a/templates/swift/guides/search/saveObjectsPublicUser.mustache +++ b/templates/swift/guides/search/saveObjectsPublicUser.mustache @@ -9,11 +9,7 @@ import Core func saveObjectsPublicUser() async throws { let playlists: [[String: AnyCodable]] = [] // Your records - do { - {{> snippets/init}} + {{> snippets/init}} - {{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}} - } catch { - print(error) - } + {{#dynamicSnippet}}saveObjectsPlaylistsWithUserIDPublic{{/dynamicSnippet}} } \ No newline at end of file diff --git a/templates/swift/guides/search/savePopularRecords.mustache b/templates/swift/guides/search/savePopularRecords.mustache index b61a0079e28..5c995092e38 100644 --- a/templates/swift/guides/search/savePopularRecords.mustache +++ b/templates/swift/guides/search/savePopularRecords.mustache @@ -13,23 +13,19 @@ struct Record: Codable { } func savePopularRecords() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - var records: [Record] = [] + var records: [Record] = [] - try await client.browseObjects(indexName: "YOUR_INDEX_NAME", browseParams: BrowseParamsObject(), aggregator: { (response: BrowseResponse) in - records.append(contentsOf: response.hits.map { - $0.nbFollowers < 1_000_000 ? $0 : Record( - twitterHandle: $0.twitterHandle, - nbFollowers: $0.nbFollowers, - isPopular: true - ) - }) - }) + try await client.browseObjects(indexName: "YOUR_INDEX_NAME", browseParams: BrowseParamsObject(), aggregator: { (response: BrowseResponse) in + records.append(contentsOf: response.hits.map { + $0.nbFollowers < 1_000_000 ? $0 : Record( + twitterHandle: $0.twitterHandle, + nbFollowers: $0.nbFollowers, + isPopular: true + ) + }) + }) - {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} - } catch { - print(error) - } + {{#dynamicSnippet}}saveObjectsRecords{{/dynamicSnippet}} } \ No newline at end of file diff --git a/templates/swift/guides/search/searchFuturePublishedBooks.mustache b/templates/swift/guides/search/searchFuturePublishedBooks.mustache index f4b292012bc..7ea6a9d60e5 100644 --- a/templates/swift/guides/search/searchFuturePublishedBooks.mustache +++ b/templates/swift/guides/search/searchFuturePublishedBooks.mustache @@ -7,17 +7,13 @@ import Core {{> snippets/import}} func searchFuturePublishedBooks() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - let dateTimestamp = Int(Date().timeIntervalSince1970) - let searchParams = SearchSearchParams.searchSearchParamsObject( - SearchSearchParamsObject(query: "", filters: "date_timestamp > \(dateTimestamp)") - ) + let dateTimestamp = Int(Date().timeIntervalSince1970) + let searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject(query: "", filters: "date_timestamp > \(dateTimestamp)") + ) - let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - print(response) - } catch { - print(error) - } + let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + print(response) } \ No newline at end of file diff --git a/templates/swift/guides/search/searchInReplicaIndex.mustache b/templates/swift/guides/search/searchInReplicaIndex.mustache index f880c92564c..ee1329b4015 100644 --- a/templates/swift/guides/search/searchInReplicaIndex.mustache +++ b/templates/swift/guides/search/searchInReplicaIndex.mustache @@ -7,18 +7,15 @@ import Core {{> snippets/import}} func searchInReplicaIndex() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - // 1. Change the sort dynamically based on the UI events - let sortByPrice = false + // 1. Change the sort dynamically based on the UI events + let sortByPrice = false - // 2. Get the index name based on sortByPrice - let indexName = sortByPrice ? "products_price_desc" : "products" + // 2. Get the index name based on sortByPrice + let indexName = sortByPrice ? "products_price_desc" : "products" - // 3. Search on dynamic index name (primary or replica) - let _: SearchResponse = {{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}} - } catch { - print(error) - } + // 3. Search on dynamic index name (primary or replica) + let response: SearchResponse = {{#dynamicSnippet}}searchWithIndexNameVar{{/dynamicSnippet}} + print(response) } diff --git a/templates/swift/guides/search/searchRecentlyPublishedBooks.mustache b/templates/swift/guides/search/searchRecentlyPublishedBooks.mustache index 501fbbe69f5..8e6b3fbf54e 100644 --- a/templates/swift/guides/search/searchRecentlyPublishedBooks.mustache +++ b/templates/swift/guides/search/searchRecentlyPublishedBooks.mustache @@ -7,17 +7,13 @@ import Core {{> snippets/import}} func searchRecentlyPublishedBooks() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - let dateTimestamp = Int(Date().timeIntervalSince1970) - 365 * 24 * 60 * 60 - let searchParams = SearchSearchParams.searchSearchParamsObject( - SearchSearchParamsObject(query: "", filters: "date_timestamp > \(dateTimestamp)") - ) + let dateTimestamp = Int(Date().timeIntervalSince1970) - 365 * 24 * 60 * 60 + let searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject(query: "", filters: "date_timestamp > \(dateTimestamp)") + ) - let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - print(response) - } catch { - print(error) - } + let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + print(response) } \ No newline at end of file diff --git a/templates/swift/guides/search/searchWithAnalyticsAndHeader.mustache b/templates/swift/guides/search/searchWithAnalyticsAndHeader.mustache index fbcfa2c6a42..69d194363fe 100644 --- a/templates/swift/guides/search/searchWithAnalyticsAndHeader.mustache +++ b/templates/swift/guides/search/searchWithAnalyticsAndHeader.mustache @@ -7,26 +7,23 @@ import Core {{> snippets/import}} func searchWithAnalyticsAndHeader() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - /* - '94.228.178.246' should be replaced with your user's IP address. - Depending on your stack there are multiple ways to get this information. - */ - let ip = "94.228.178.246" - let query = "query" + /* + '94.228.178.246' should be replaced with your user's IP address. + Depending on your stack there are multiple ways to get this information. + */ + let ip = "94.228.178.246" + let query = "query" - let searchParams = SearchSearchParams.searchSearchParamsObject( - SearchSearchParamsObject( - query: query, - analytics: true - ) - ) + let searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject( + query: query, + analytics: true + ) + ) - let _: SearchResponse = {{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}} - } catch { - print(error) - } + let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParamsAndForwardedHeader{{/dynamicSnippet}} + print(response) } diff --git a/templates/swift/guides/search/searchWithGAToken.mustache b/templates/swift/guides/search/searchWithGAToken.mustache index a4b679e6bc9..077de00e7db 100644 --- a/templates/swift/guides/search/searchWithGAToken.mustache +++ b/templates/swift/guides/search/searchWithGAToken.mustache @@ -11,23 +11,20 @@ let getGoogleAnalyticsUserIdFromBrowserCookie = {(_: String) in } func searchWithGAToken() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - let userToken = getGoogleAnalyticsUserIdFromBrowserCookie("_ga"); - var searchParams = SearchSearchParams.searchSearchParamsObject( - SearchSearchParamsObject(query: "", userToken: userToken) - ) + let userToken = getGoogleAnalyticsUserIdFromBrowserCookie("_ga"); + var searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject(query: "", userToken: userToken) + ) - let _: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + let _: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - let loggedInUser: String? = "..." - searchParams = SearchSearchParams.searchSearchParamsObject( - SearchSearchParamsObject(query: "", userToken: loggedInUser ?? userToken) - ) + let loggedInUser: String? = "..." + searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject(query: "", userToken: loggedInUser ?? userToken) + ) - let _: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - } catch { - print(error) - } + let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + print(response) } \ No newline at end of file diff --git a/templates/swift/guides/search/searchWithLogicalOr.mustache b/templates/swift/guides/search/searchWithLogicalOr.mustache index e6625d6c743..2427091e550 100644 --- a/templates/swift/guides/search/searchWithLogicalOr.mustache +++ b/templates/swift/guides/search/searchWithLogicalOr.mustache @@ -7,18 +7,15 @@ import Core {{> snippets/import}} func searchWithLogicalOr() async throws { - do { - {{> snippets/init}} - let query = "the query" - let optionalWords = ["the", "query"]; - let searchParams = SearchSearchParams.searchSearchParamsObject( - SearchSearchParamsObject( - query: query, - optionalWords: .arrayOfString(optionalWords) - ) + {{> snippets/init}} + let query = "the query" + let optionalWords = ["the", "query"]; + let searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject( + query: query, + optionalWords: .arrayOfString(optionalWords) ) - let _: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - } catch { - print(error) - } + ) + let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + print(response) } \ No newline at end of file diff --git a/templates/swift/guides/search/searchWithOptionalFilters.mustache b/templates/swift/guides/search/searchWithOptionalFilters.mustache index 185a015b15c..da857ad1834 100644 --- a/templates/swift/guides/search/searchWithOptionalFilters.mustache +++ b/templates/swift/guides/search/searchWithOptionalFilters.mustache @@ -13,17 +13,13 @@ let reduceLabelsToFilters = {(_: [String]) in } func searchWithOptionalFilters() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - let optionalFilters = reduceLabelsToFilters(labels) - let searchParams = SearchSearchParams.searchSearchParamsObject( - SearchSearchParamsObject(query: "", optionalFilters: optionalFilters) - ) + let optionalFilters = reduceLabelsToFilters(labels) + let searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject(query: "", optionalFilters: optionalFilters) + ) - let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - print(response) - } catch { - print(error) - } + let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + print(response) } \ No newline at end of file diff --git a/templates/swift/guides/search/searchWithRuleContextBuyer.mustache b/templates/swift/guides/search/searchWithRuleContextBuyer.mustache index 25c58a260a2..93e7cb9ce47 100644 --- a/templates/swift/guides/search/searchWithRuleContextBuyer.mustache +++ b/templates/swift/guides/search/searchWithRuleContextBuyer.mustache @@ -9,18 +9,14 @@ import Core let getBuyerAccountId = {""} // Implement your logic here func searchWithRuleContextBuyer() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - // get the buyer account information - let buyer = getBuyerAccountId(); - let searchParams = SearchSearchParams.searchSearchParamsObject( - SearchSearchParamsObject(query: "", ruleContexts: [buyer]) - ) + // get the buyer account information + let buyer = getBuyerAccountId(); + let searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject(query: "", ruleContexts: [buyer]) + ) - let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - print(response) - } catch { - print(error) - } + let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + print(response) } \ No newline at end of file diff --git a/templates/swift/guides/search/searchWithRuleContexts.mustache b/templates/swift/guides/search/searchWithRuleContexts.mustache index 859bf8b8aec..5236bf5d046 100644 --- a/templates/swift/guides/search/searchWithRuleContexts.mustache +++ b/templates/swift/guides/search/searchWithRuleContexts.mustache @@ -9,17 +9,13 @@ import Core let getPlatformTag = {""} // Implement your logic here func searchWithRuleContexts() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - let platformTag = getPlatformTag() - let searchParams = SearchSearchParams.searchSearchParamsObject( - SearchSearchParamsObject(query: "", ruleContexts: [platformTag]) - ) + let platformTag = getPlatformTag() + let searchParams = SearchSearchParams.searchSearchParamsObject( + SearchSearchParamsObject(query: "", ruleContexts: [platformTag]) + ) - let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} - print(response) - } catch { - print(error) - } + let response: SearchResponse = {{#dynamicSnippet}}searchWithSearchParams{{/dynamicSnippet}} + print(response) } \ No newline at end of file diff --git a/templates/swift/guides/search/setHeaderUserIDThenSaveObjects.mustache b/templates/swift/guides/search/setHeaderUserIDThenSaveObjects.mustache index 91352d013ba..a21e576612d 100644 --- a/templates/swift/guides/search/setHeaderUserIDThenSaveObjects.mustache +++ b/templates/swift/guides/search/setHeaderUserIDThenSaveObjects.mustache @@ -9,14 +9,14 @@ import Core func setHeaderUserIDThenSaveObjects() async throws { let playlists: [[String: AnyCodable]] = [/* Your records */] - do { - {{> snippets/init}} + {{> snippets/init}} - for playlist in playlists { + for playlist in playlists { + do { let playlistUserID = playlist["userID"]?.value as! String {{#dynamicSnippet}}saveObjectsPlaylistsWithRequestOptions{{/dynamicSnippet}} + } catch { + print(error) } - } catch { - print(error) } } \ No newline at end of file diff --git a/templates/swift/guides/search/useConditionlessRule.mustache b/templates/swift/guides/search/useConditionlessRule.mustache index e28e20cd8f3..61ae29bf93f 100644 --- a/templates/swift/guides/search/useConditionlessRule.mustache +++ b/templates/swift/guides/search/useConditionlessRule.mustache @@ -7,27 +7,23 @@ import Core {{> snippets/import}} func useConditionlessRule() async throws { - do { - {{> snippets/init}} + {{> snippets/init}} - let objectID = "a-rule-id"; + let objectID = "a-rule-id"; - let rule = Rule( - objectID: objectID, - consequence: SearchConsequence( - // Set relevant consequence - ), - // Set validity (optional) - validity: [ - SearchTimeRange( - from: 1_688_774_400, - until: 1_738_972_800 - ) - ] - ) + let rule = Rule( + objectID: objectID, + consequence: SearchConsequence( + // Set relevant consequence + ), + // Set validity (optional) + validity: [ + SearchTimeRange( + from: 1_688_774_400, + until: 1_738_972_800 + ) + ] + ) - {{#dynamicSnippet}}saveRule{{/dynamicSnippet}} - } catch { - print(error) - } + {{#dynamicSnippet}}saveRule{{/dynamicSnippet}} } \ No newline at end of file diff --git a/tests/CTS/client/search/generateSecuredApiKey.json b/tests/CTS/client/search/generateSecuredApiKey.json index a914508a0cf..9f1ef6c0430 100644 --- a/tests/CTS/client/search/generateSecuredApiKey.json +++ b/tests/CTS/client/search/generateSecuredApiKey.json @@ -102,5 +102,35 @@ } } ] + }, + { + "testName": "mcm with filters", + "steps": [ + { + "type": "method", + "method": "generateSecuredApiKey", + "parameters": { + "parentApiKey": "YourSearchOnlyApiKey", + "restrictions": { + "filters": "user:user42 AND user:public" + } + } + } + ] + }, + { + "testName": "mcm with user token", + "steps": [ + { + "type": "method", + "method": "generateSecuredApiKey", + "parameters": { + "parentApiKey": "YourSearchOnlyApiKey", + "restrictions": { + "userToken": "user42" + } + } + } + ] } ] diff --git a/tests/CTS/guides/search.json b/tests/CTS/guides/search.json index d24b3d41395..87712a38e93 100644 --- a/tests/CTS/guides/search.json +++ b/tests/CTS/guides/search.json @@ -6,6 +6,14 @@ "objects": "$var: movies" } }, + "partialUpdatesRecords": { + "method": "partialUpdateObjects", + "parameters": { + "indexName": "products", + "objects": "$var: records", + "createIfNotExists": true + } + }, "saveObjectsChunks": { "method": "saveObjects", "parameters": { @@ -121,6 +129,12 @@ } } }, + "getSettings": { + "method": "getSettings", + "parameters": { + "indexName": "indexName" + } + }, "setSettings": { "method": "setSettings", "parameters": { diff --git a/tests/CTS/requests/search/saveRule.json b/tests/CTS/requests/search/saveRule.json index 9cbd51e5b40..b82a4aa49c7 100644 --- a/tests/CTS/requests/search/saveRule.json +++ b/tests/CTS/requests/search/saveRule.json @@ -989,5 +989,44 @@ } } } + }, + { + "testName": "saveRule always active rule", + "parameters": { + "indexName": "indexName", + "objectID": "a-rule-id", + "rule": { + "objectID": "a-rule-id", + "consequence": { + "params": { + "aroundRadius": 1000 + } + }, + "validity": [ + { + "from": 1577836800, + "until": 1577836800 + } + ] + } + }, + "request": { + "path": "/1/indexes/indexName/rules/a-rule-id", + "method": "PUT", + "body": { + "objectID": "a-rule-id", + "consequence": { + "params": { + "aroundRadius": 1000 + } + }, + "validity": [ + { + "from": 1577836800, + "until": 1577836800 + } + ] + } + } } ] diff --git a/tests/CTS/requests/search/searchSingleIndex.json b/tests/CTS/requests/search/searchSingleIndex.json index 418b8296e08..6dcb1225c18 100644 --- a/tests/CTS/requests/search/searchSingleIndex.json +++ b/tests/CTS/requests/search/searchSingleIndex.json @@ -2812,5 +2812,26 @@ "query": "query" } } + }, + { + "testName": "mcm with algolia user id", + "parameters": { + "indexName": "playlists", + "searchParams": { + "query": "peace" + } + }, + "requestOptions": { + "headers": { + "X-Algolia-User-ID": "user42" + } + }, + "request": { + "path": "/1/indexes/playlists/query", + "method": "POST", + "body": { + "query": "peace" + } + } } ]