├── .gitattributes
├── .gitignore
├── CONTRIBUTING.md
├── DotNetHowTo
├── DotNetHowTo.sln
└── DotNetHowTo
│ ├── Address.Methods.cs
│ ├── Address.cs
│ ├── DotNetHowTo.csproj
│ ├── Hotel.Methods.cs
│ ├── Hotel.cs
│ ├── Program.cs
│ ├── Room.Methods.cs
│ ├── Room.cs
│ └── appsettings.json
├── DotNetHowToEncryptionUsingCMK
├── DotNetHowToEncryptionUsingCMK.sln
└── DotNetHowToEncryptionUsingCMK
│ ├── DotNetHowToEncryptionUsingCMK.csproj
│ ├── Hotel.Methods.cs
│ ├── Hotel.cs
│ ├── Program.cs
│ └── appsettings.json
├── DotNetHowToIndexers
├── DotNetHowToIndexers.csproj
├── DotNetHowToIndexers.sln
├── Hotel.cs
├── Program.cs
├── appsettings.json
└── hotels.sql
├── LICENSE
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.bmp binary
2 | *.dll binary
3 | *.gif binary
4 | *.jpg binary
5 | *.png binary
6 | *.snk binary
7 | *.exe binary
8 | *.wmv binary
9 | *.mp4 binary
10 | *.ismv binary
11 | *.isma binary
12 |
13 | *.ascx text
14 | *.cmd text
15 | *.config text
16 | *.cs text diff=csharp
17 | *.csproj text merge=union
18 | *.edmx text
19 |
20 | *.htm text
21 | *.html text
22 |
23 | *.js text
24 | *.json text
25 |
26 | *.msbuild text
27 | *.nuspec text
28 |
29 | *.resx text
30 | *.ruleset text
31 | *.StyleCop text
32 | *.targets text
33 | *.txt text
34 | *.xml text
35 |
36 | *.sln text eol=crlf merge=union
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 | developer/
9 | .vs/
10 |
11 | # Build results
12 | binaries/
13 | [Dd]ebug*/
14 | [Rr]elease/
15 | build/
16 |
17 | [Tt]est[Rr]esult
18 | [Bb]uild[Ll]og.*
19 |
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.vspscc
36 | *.vssscc
37 | .builds
38 |
39 | *.pidb
40 |
41 | *.log
42 | *.scc
43 | # Visual C++ cache files
44 | ipch/
45 | *.aps
46 | *.ncb
47 | *.opensdf
48 | *.sdf
49 |
50 | # Visual Studio profiler
51 | *.psess
52 | *.vsp
53 |
54 | # Code analysis
55 | *.CodeAnalysisLog.xml
56 |
57 | # Guidance Automation Toolkit
58 | *.gpState
59 |
60 | # ReSharper is a .NET coding add-in
61 | _ReSharper*/
62 |
63 | *.[Rr]e[Ss]harper
64 |
65 | # NCrunch
66 | *.ncrunch*
67 | .*crunch*.local.xml
68 |
69 | # Installshield output folder
70 | [Ee]xpress
71 |
72 | # DocProject is a documentation generator add-in
73 | DocProject/buildhelp/
74 | DocProject/Help/*.HxT
75 | DocProject/Help/*.HxC
76 | DocProject/Help/*.hhc
77 | DocProject/Help/*.hhk
78 | DocProject/Help/*.hhp
79 | DocProject/Help/Html2
80 | DocProject/Help/html
81 |
82 | # Click-Once directory
83 | publish
84 |
85 | # Publish Web Output
86 | *.Publish.xml
87 |
88 | # Others
89 | [Bb]in
90 | [Oo]bj
91 | sql
92 | TestResults
93 | [Tt]est[Rr]esult*
94 | *.Cache
95 | ClientBin
96 | [Ss]tyle[Cc]op.*
97 | ~$*
98 | *.dbmdl
99 |
100 | *.[Pp]ublish.xml
101 |
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Build tasks
105 | tools/*.dll
106 |
107 | # Sensitive files
108 | *.keys
109 | *.pfx
110 |
111 | # Backup & report files from converting an old project file to a newer
112 | # Visual Studio version. Backup files are not needed, because we have git ;-)
113 | _UpgradeReport_Files/
114 | Backup*/
115 | UpgradeLog*.XML
116 |
117 | # NuGet
118 | packages
119 |
120 | # Mac development
121 | .DS_Store
122 |
123 | # Specification DLLs
124 | *.Specification.dll
125 |
126 | # Generated readme.txt files #
127 | src/*/readme.txt
128 |
129 | build.out
130 | .nuget/
131 |
132 | # Azure Project
133 | csx/
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Azure samples
2 |
3 | Thank you for your interest in contributing to Azure samples!
4 |
5 | ## Ways to contribute
6 |
7 | You can contribute to [Azure samples](https://azure.microsoft.com/documentation/samples/) in a few different ways:
8 |
9 | - Submit feedback on [this sample page](https://azure.microsoft.com/documentation/samples/search-dotnet-getting-started/) whether it was helpful or not.
10 | - Submit issues through [issue tracker](https://github.com/Azure-Samples/search-dotnet-getting-started/issues) on GitHub. We are actively monitoring the issues and improving our samples.
11 | - If you wish to make code changes to samples, or contribute something new, please follow the [GitHub Forks / Pull requests model](https://help.github.com/articles/fork-a-repo/): Fork the sample repo, make the change and propose it back by submitting a pull request.
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26403.7
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetHowTo", "DotNetHowTo\DotNetHowTo.csproj", "{7A8E8FFE-D264-45DE-8569-689F2BB5EB61}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {7A8E8FFE-D264-45DE-8569-689F2BB5EB61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {7A8E8FFE-D264-45DE-8569-689F2BB5EB61}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {7A8E8FFE-D264-45DE-8569-689F2BB5EB61}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {7A8E8FFE-D264-45DE-8569-689F2BB5EB61}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo/Address.Methods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Text.Json.Serialization;
4 |
5 | namespace AzureSearch.SDKHowTo
6 | {
7 | public partial class Address
8 | {
9 | // This implementation of ToString() is only for the purposes of the sample console application.
10 | // You can override ToString() in your own model class if you want, but you don't need to in order
11 | // to use the Azure Search .NET SDK.
12 | public override string ToString()
13 | {
14 | var builder = new StringBuilder();
15 |
16 | if (!IsEmpty)
17 | {
18 | builder.AppendFormat("{0}\n{1}, {2} {3}\n{4}", StreetAddress, City, StateProvince, PostalCode, Country);
19 | }
20 |
21 | return builder.ToString();
22 | }
23 |
24 | [JsonIgnore]
25 | public bool IsEmpty => String.IsNullOrEmpty(StreetAddress) &&
26 | String.IsNullOrEmpty(City) &&
27 | String.IsNullOrEmpty(StateProvince) &&
28 | String.IsNullOrEmpty(PostalCode) &&
29 | String.IsNullOrEmpty(Country);
30 | }
31 | }
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo/Address.cs:
--------------------------------------------------------------------------------
1 | using Azure.Search.Documents.Indexes;
2 |
3 | namespace AzureSearch.SDKHowTo
4 | {
5 | public partial class Address
6 | {
7 | [SearchableField(IsFilterable = true)]
8 | public string StreetAddress { get; set; }
9 |
10 | [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
11 | public string City { get; set; }
12 |
13 | [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
14 | public string StateProvince { get; set; }
15 |
16 | [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
17 | public string PostalCode { get; set; }
18 |
19 | [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
20 | public string Country { get; set; }
21 | }
22 | }
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo/DotNetHowTo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | PreserveNewest
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo/Hotel.Methods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace AzureSearch.SDKHowTo
5 | {
6 | public partial class Hotel
7 | {
8 | // This implementation of ToString() is only for the purposes of the sample console application.
9 | // You can override ToString() in your own model class if you want, but you don't need to in order
10 | // to use the Azure Search .NET SDK.
11 | public override string ToString()
12 | {
13 | var builder = new StringBuilder();
14 |
15 | if (!String.IsNullOrEmpty(HotelId))
16 | {
17 | builder.AppendFormat("HotelId: {0}\n", HotelId);
18 | }
19 |
20 | if (!String.IsNullOrEmpty(HotelName))
21 | {
22 | builder.AppendFormat("Name: {0}\n", HotelName);
23 | }
24 |
25 | if (!String.IsNullOrEmpty(Description))
26 | {
27 | builder.AppendFormat("Description: {0}\n", Description);
28 | }
29 |
30 | if (!String.IsNullOrEmpty(DescriptionFr))
31 | {
32 | builder.AppendFormat("Description (French): {0}\n", DescriptionFr);
33 | }
34 |
35 | if (!String.IsNullOrEmpty(Category))
36 | {
37 | builder.AppendFormat("Category: {0}\n", Category);
38 | }
39 |
40 | if (Tags != null && Tags.Length > 0)
41 | {
42 | builder.AppendFormat("Tags: [ {0} ]\n", String.Join(", ", Tags));
43 | }
44 |
45 | if (ParkingIncluded.HasValue)
46 | {
47 | builder.AppendFormat("Parking included: {0}\n", ParkingIncluded.Value ? "yes" : "no");
48 | }
49 |
50 | if (SmokingAllowed.HasValue)
51 | {
52 | builder.AppendFormat("Smoking allowed: {0}\n", SmokingAllowed.Value ? "yes" : "no");
53 | }
54 |
55 | if (LastRenovationDate.HasValue)
56 | {
57 | builder.AppendFormat("Last renovated on: {0}\n", LastRenovationDate);
58 | }
59 |
60 | if (Rating.HasValue)
61 | {
62 | builder.AppendFormat("Rating: {0}\n", Rating);
63 | }
64 |
65 | if (Address != null && !Address.IsEmpty)
66 | {
67 | builder.AppendFormat("Address: \n{0}\n", Address.ToString());
68 | }
69 |
70 | if (Location != null)
71 | {
72 | builder.AppendFormat("Location: Latitude {0}, Longitude {1}\n", Location.Latitude, Location.Longitude);
73 | }
74 |
75 | if (Rooms != null)
76 | {
77 | builder.AppendFormat("\nRooms: \n");
78 | foreach (var room in Rooms)
79 | {
80 | if (room != null)
81 | {
82 | builder.AppendFormat("{0}\n\n", room.ToString());
83 | }
84 | }
85 | }
86 |
87 | return builder.ToString();
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo/Hotel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Spatial;
3 | using System.Text.Json.Serialization;
4 | using Azure.Search.Documents.Indexes;
5 | using Azure.Search.Documents.Indexes.Models;
6 |
7 | namespace AzureSearch.SDKHowTo
8 | {
9 | public partial class Hotel
10 | {
11 | [SimpleField(IsKey = true, IsFilterable = true)]
12 | public string HotelId { get; set; }
13 |
14 | [SearchableField(IsSortable = true)]
15 | public string HotelName { get; set; }
16 |
17 | [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)]
18 | public string Description { get; set; }
19 |
20 | [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)]
21 | [JsonPropertyName("Description_fr")]
22 | public string DescriptionFr { get; set; }
23 |
24 | [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
25 | public string Category { get; set; }
26 |
27 | [SearchableField(IsFilterable = true, IsFacetable = true)]
28 | public string[] Tags { get; set; }
29 |
30 | [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
31 | public bool? ParkingIncluded { get; set; }
32 |
33 | // SmokingAllowed reflects whether any room in the hotel allows smoking.
34 | // The JsonIgnore attribute indicates that a field should not be created
35 | // in the index for this property and it will only be used by code in the client.
36 | [JsonIgnore]
37 | public bool? SmokingAllowed => (Rooms != null) ? Array.Exists(Rooms, element => element.SmokingAllowed == true) : (bool?)null;
38 |
39 | [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
40 | public DateTimeOffset? LastRenovationDate { get; set; }
41 |
42 | [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
43 | public double? Rating { get; set; }
44 |
45 | [SearchableField]
46 | public Address Address { get; set; }
47 |
48 | [JsonConverter(typeof(Azure.Core.Serialization.MicrosoftSpatialGeoJsonConverter))]
49 | [SimpleField(IsFilterable = true, IsSortable = true)]
50 | public GeographyPoint Location { get; set; }
51 |
52 | public Room[] Rooms { get; set; }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo/Program.cs:
--------------------------------------------------------------------------------
1 | #define HowToExample
2 | using System;
3 | using System.Threading;
4 | using Azure;
5 | using Azure.Search.Documents;
6 | using Azure.Search.Documents.Indexes;
7 | using Azure.Search.Documents.Indexes.Models;
8 | using Azure.Search.Documents.Models;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Spatial;
11 |
12 | namespace AzureSearch.SDKHowTo
13 | {
14 | class Program
15 | {
16 | // This sample shows how to delete, create, upload documents and query an index
17 | static void Main(string[] args)
18 | {
19 | IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
20 | IConfigurationRoot configuration = builder.Build();
21 |
22 | SearchIndexClient indexClient = CreateSearchIndexClient(configuration);
23 |
24 | string indexName = configuration["SearchIndexName"];
25 |
26 | Console.WriteLine("{0}", "Deleting index...\n");
27 | DeleteIndexIfExists(indexName, indexClient);
28 |
29 | Console.WriteLine("{0}", "Creating index...\n");
30 | CreateIndex(indexName, indexClient);
31 |
32 | SearchClient searchClient = indexClient.GetSearchClient(indexName);
33 |
34 | Console.WriteLine("{0}", "Uploading documents...\n");
35 | UploadDocuments(searchClient);
36 |
37 | SearchClient indexClientForQueries = CreateSearchClientForQueries(indexName, configuration);
38 |
39 | RunQueries(indexClientForQueries);
40 |
41 | Console.WriteLine("{0}", "Complete. Press any key to end application...\n");
42 | Console.ReadKey();
43 | }
44 |
45 | private static SearchIndexClient CreateSearchIndexClient(IConfigurationRoot configuration)
46 | {
47 | string searchServiceEndPoint = configuration["SearchServiceEndPoint"];
48 | string adminApiKey = configuration["SearchServiceAdminApiKey"];
49 |
50 | SearchIndexClient indexClient = new SearchIndexClient(new Uri(searchServiceEndPoint), new AzureKeyCredential(adminApiKey));
51 | return indexClient;
52 | }
53 |
54 | private static SearchClient CreateSearchClientForQueries(string indexName, IConfigurationRoot configuration)
55 | {
56 | string searchServiceEndPoint = configuration["SearchServiceEndPoint"];
57 | string queryApiKey = configuration["SearchServiceQueryApiKey"];
58 |
59 | SearchClient searchClient = new SearchClient(new Uri(searchServiceEndPoint), indexName, new AzureKeyCredential(queryApiKey));
60 | return searchClient;
61 | }
62 |
63 | private static void DeleteIndexIfExists(string indexName, SearchIndexClient indexClient)
64 | {
65 | try
66 | {
67 | if (indexClient.GetIndex(indexName) != null)
68 | {
69 | indexClient.DeleteIndex(indexName);
70 | }
71 | }
72 | catch (RequestFailedException e) when (e.Status == 404)
73 | {
74 | //if exception occurred and status is "Not Found", this is work as expect
75 | Console.WriteLine("Failed to find index and this is because it's not there.");
76 | }
77 | }
78 |
79 | private static void CreateIndex(string indexName, SearchIndexClient indexClient)
80 | {
81 | FieldBuilder fieldBuilder = new FieldBuilder();
82 | var searchFields = fieldBuilder.Build(typeof(Hotel));
83 |
84 | var definition = new SearchIndex(indexName, searchFields);
85 |
86 | indexClient.CreateOrUpdateIndex(definition);
87 | }
88 |
89 | #if HowToExample
90 |
91 | // Upload documents in a single Upload request.
92 | private static void UploadDocuments(SearchClient searchClient)
93 | {
94 | IndexDocumentsBatch batch = IndexDocumentsBatch.Create(
95 | IndexDocumentsAction.Upload(
96 | new Hotel()
97 | {
98 | HotelId = "1",
99 | HotelName = "Secret Point Motel",
100 | Description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
101 | DescriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
102 | Category = "Boutique",
103 | Tags = new[] { "pool", "air conditioning", "concierge" },
104 | ParkingIncluded = false,
105 | LastRenovationDate = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
106 | Rating = 3.6,
107 | Location = GeographyPoint.Create(40.760586, -73.975403),
108 | Address = new Address()
109 | {
110 | StreetAddress = "677 5th Ave",
111 | City = "New York",
112 | StateProvince = "NY",
113 | PostalCode = "10022",
114 | Country = "USA"
115 | },
116 | Rooms = new Room[]
117 | {
118 | new Room()
119 | {
120 | Description = "Budget Room, 1 Queen Bed (Cityside)",
121 | DescriptionFr = "Chambre Économique, 1 grand lit (côté ville)",
122 | Type = "Budget Room",
123 | BaseRate = 96.99,
124 | BedOptions = "1 Queen Bed",
125 | SleepsCount = 2,
126 | SmokingAllowed = true,
127 | Tags = new[] { "vcr/dvd" }
128 | },
129 | new Room()
130 | {
131 | Description = "Budget Room, 1 King Bed (Mountain View)",
132 | DescriptionFr = "Chambre Économique, 1 très grand lit (Mountain View)",
133 | Type = "Budget Room",
134 | BaseRate = 80.99,
135 | BedOptions = "1 King Bed",
136 | SleepsCount = 2,
137 | SmokingAllowed = true,
138 | Tags = new[] { "vcr/dvd", "jacuzzi tub" }
139 | },
140 | new Room()
141 | {
142 | Description = "Deluxe Room, 2 Double Beds (City View)",
143 | DescriptionFr = "Chambre Deluxe, 2 lits doubles (vue ville)",
144 | Type = "Deluxe Room",
145 | BaseRate = 150.99,
146 | BedOptions = "2 Double Beds",
147 | SleepsCount = 2,
148 | SmokingAllowed = false,
149 | Tags = new[] { "suite", "bathroom shower", "coffee maker" }
150 | }
151 | }
152 | }),
153 | IndexDocumentsAction.Upload(
154 | new Hotel()
155 | {
156 | HotelId = "2",
157 | HotelName = "Twin Dome Motel",
158 | Description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
159 | DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
160 | Category = "Boutique",
161 | Tags = new[] { "pool", "free wifi", "concierge" },
162 | ParkingIncluded = false,
163 | LastRenovationDate = new DateTimeOffset(1979, 2, 18, 0, 0, 0, TimeSpan.Zero),
164 | Rating = 3.60,
165 | Location = GeographyPoint.Create(27.384417, -82.452843),
166 | Address = new Address()
167 | {
168 | StreetAddress = "140 University Town Center Dr",
169 | City = "Sarasota",
170 | StateProvince = "FL",
171 | PostalCode = "34243",
172 | Country = "USA"
173 | },
174 | Rooms = new Room[]
175 | {
176 | new Room()
177 | {
178 | Description = "Suite, 2 Double Beds (Mountain View)",
179 | DescriptionFr = "Suite, 2 lits doubles (vue sur la montagne)",
180 | Type = "Suite",
181 | BaseRate = 250.99,
182 | BedOptions = "2 Double Beds",
183 | SleepsCount = 2,
184 | SmokingAllowed = false,
185 | Tags = new[] { "Room Tags" }
186 | },
187 | new Room()
188 | {
189 | Description = "Standard Room, 1 Queen Bed (City View)",
190 | DescriptionFr = "Chambre Standard, 1 grand lit (vue ville)",
191 | Type = "Standard Room",
192 | BaseRate = 121.99,
193 | BedOptions = "1 Queen Bed",
194 | SleepsCount = 2,
195 | SmokingAllowed = false,
196 | Tags = new[] { "jacuzzi tub" }
197 | },
198 | new Room()
199 | {
200 | Description = "Budget Room, 1 King Bed (Waterfront View)",
201 | DescriptionFr = "Chambre Économique, 1 très grand lit (vue sur le front de mer)",
202 | Type = "Budget Room",
203 | BaseRate = 88.99,
204 | BedOptions = "1 King Bed",
205 | SleepsCount = 2,
206 | SmokingAllowed = false,
207 | Tags = new[] { "suite", "tv", "jacuzzi tub" }
208 | }
209 | }
210 | }),
211 | IndexDocumentsAction.Upload(
212 | new Hotel()
213 | {
214 | HotelId = "3",
215 | HotelName = "Triple Landscape Hotel",
216 | Description = "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
217 | DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
218 | Category = "Resort and Spa",
219 | Tags = new[] { "air conditioning", "bar", "continental breakfast" },
220 | ParkingIncluded = true,
221 | LastRenovationDate = new DateTimeOffset(2015, 9, 20, 0, 0, 0, TimeSpan.Zero),
222 | Rating = 4.80,
223 | Location = GeographyPoint.Create(33.84643, -84.362465),
224 | Address = new Address()
225 | {
226 | StreetAddress = "3393 Peachtree Rd",
227 | City = "Atlanta",
228 | StateProvince = "GA",
229 | PostalCode = "30326",
230 | Country = "USA"
231 | },
232 | Rooms = new Room[]
233 | {
234 | new Room()
235 | {
236 | Description = "Standard Room, 2 Queen Beds (Amenities)",
237 | DescriptionFr = "Chambre Standard, 2 grands lits (Services)",
238 | Type = "Standard Room",
239 | BaseRate = 101.99,
240 | BedOptions = "2 Queen Beds",
241 | SleepsCount = 4,
242 | SmokingAllowed = true,
243 | Tags = new[] { "vcr/dvd", "vcr/dvd" }
244 | },
245 | new Room ()
246 | {
247 | Description = "Standard Room, 2 Double Beds (Waterfront View)",
248 | DescriptionFr = "Chambre Standard, 2 lits doubles (vue sur le front de mer)",
249 | Type = "Standard Room",
250 | BaseRate = 106.99,
251 | BedOptions = "2 Double Beds",
252 | SleepsCount = 2,
253 | SmokingAllowed = true,
254 | Tags = new[] { "coffee maker" }
255 | },
256 | new Room()
257 | {
258 | Description = "Deluxe Room, 2 Double Beds (Cityside)",
259 | DescriptionFr = "Chambre Deluxe, 2 lits doubles (Cityside)",
260 | Type = "Budget Room",
261 | BaseRate = 180.99,
262 | BedOptions = "2 Double Beds",
263 | SleepsCount = 2,
264 | SmokingAllowed = true,
265 | Tags = new[] { "suite" }
266 | }
267 | }
268 | }));
269 |
270 | try
271 | {
272 | IndexDocumentsResult result = searchClient.IndexDocuments(batch);
273 | }
274 | catch (Exception)
275 | {
276 | // Sometimes when your Search service is under load, indexing will fail for some of the documents in
277 | // the batch. Depending on your application, you can take compensating actions like delaying and
278 | // retrying. For this simple demo, we just log the failed document keys and continue.
279 | Console.WriteLine("Failed to index some of the documents: {0}");
280 | }
281 |
282 | Console.WriteLine("Waiting for documents to be indexed...\n");
283 | Thread.Sleep(2000);
284 | }
285 |
286 | #else
287 | // Upload documents as a batch.
288 | private static void UploadDocuments(SearchClient searchClient)
289 | {
290 | IndexDocumentsBatch batch = IndexDocumentsBatch.Create(
291 | IndexDocumentsAction.Upload(
292 | new Hotel()
293 | {
294 | HotelId = "1",
295 | HotelName = "Secret Point Motel",
296 | Description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
297 | DescriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
298 | Category = "Boutique",
299 | Tags = new[] { "pool", "air conditioning", "concierge" },
300 | ParkingIncluded = false,
301 | LastRenovationDate = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
302 | Rating = 3.6,
303 | Location = GeographyPoint.Create(40.760586, -73.975403),
304 | Address = new Address()
305 | {
306 | StreetAddress = "677 5th Ave",
307 | City = "New York",
308 | StateProvince = "NY",
309 | PostalCode = "10022",
310 | Country = "USA"
311 | },
312 | Rooms = new Room[]
313 | {
314 | new Room()
315 | {
316 | Description = "Budget Room, 1 Queen Bed (Cityside)",
317 | DescriptionFr = "Chambre Économique, 1 grand lit (côté ville)",
318 | Type = "Budget Room",
319 | BaseRate = 96.99,
320 | BedOptions = "1 Queen Bed",
321 | SleepsCount = 2,
322 | SmokingAllowed = true,
323 | Tags = new[] { "vcr/dvd" }
324 | },
325 | new Room()
326 | {
327 | Description = "Budget Room, 1 King Bed (Mountain View)",
328 | DescriptionFr = "Chambre Économique, 1 très grand lit (Mountain View)",
329 | Type = "Budget Room",
330 | BaseRate = 80.99,
331 | BedOptions = "1 King Bed",
332 | SleepsCount = 2,
333 | SmokingAllowed = true,
334 | Tags = new[] { "vcr/dvd", "jacuzzi tub" }
335 | },
336 | new Room()
337 | {
338 | Description = "Deluxe Room, 2 Double Beds (City View)",
339 | DescriptionFr = "Chambre Deluxe, 2 lits doubles (vue ville)",
340 | Type = "Deluxe Room",
341 | BaseRate = 150.99,
342 | BedOptions = "2 Double Beds",
343 | SleepsCount = 2,
344 | SmokingAllowed = false,
345 | Tags = new[] { "suite", "bathroom shower", "coffee maker" }
346 | }
347 | }
348 | }
349 | ),
350 | IndexDocumentsAction.Upload(
351 | new Hotel()
352 | {
353 | HotelId = "2",
354 | HotelName = "Twin Dome Motel",
355 | Description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
356 | DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
357 | Category = "Boutique",
358 | Tags = new[] { "pool", "free wifi", "concierge" },
359 | ParkingIncluded = false,
360 | LastRenovationDate = new DateTimeOffset(1979, 2, 18, 0, 0, 0, TimeSpan.Zero),
361 | Rating = 3.60,
362 | Location = GeographyPoint.Create(27.384417, -82.452843),
363 | Address = new Address()
364 | {
365 | StreetAddress = "140 University Town Center Dr",
366 | City = "Sarasota",
367 | StateProvince = "FL",
368 | PostalCode = "34243",
369 | Country = "USA"
370 | },
371 | Rooms = new Room[]
372 | {
373 | new Room()
374 | {
375 | Description = "Suite, 2 Double Beds (Mountain View)",
376 | DescriptionFr = "Suite, 2 lits doubles (vue sur la montagne)",
377 | Type = "Suite",
378 | BaseRate = 250.99,
379 | BedOptions = "2 Double Beds",
380 | SleepsCount = 2,
381 | SmokingAllowed = false,
382 | Tags = new[] { "Room Tags" }
383 | },
384 | new Room()
385 | {
386 | Description = "Standard Room, 1 Queen Bed (City View)",
387 | DescriptionFr = "Chambre Standard, 1 grand lit (vue ville)",
388 | Type = "Standard Room",
389 | BaseRate = 121.99,
390 | BedOptions = "1 Queen Bed",
391 | SleepsCount = 2,
392 | SmokingAllowed = false,
393 | Tags = new[] { "jacuzzi tub" }
394 | },
395 | new Room()
396 | {
397 | Description = "Budget Room, 1 King Bed (Waterfront View)",
398 | DescriptionFr = "Chambre Économique, 1 très grand lit (vue sur le front de mer)",
399 | Type = "Budget Room",
400 | BaseRate = 88.99,
401 | BedOptions = "1 King Bed",
402 | SleepsCount = 2,
403 | SmokingAllowed = false,
404 | Tags = new[] { "suite", "tv", "jacuzzi tub" }
405 | }
406 | }
407 | }
408 | ),
409 | IndexDocumentsAction.Upload(
410 | new Hotel()
411 | {
412 | HotelId = "3",
413 | HotelName = "Triple Landscape Hotel",
414 | Description = "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
415 | DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
416 | Category = "Resort and Spa",
417 | Tags = new[] { "air conditioning", "bar", "continental breakfast" },
418 | ParkingIncluded = true,
419 | LastRenovationDate = new DateTimeOffset(2015, 9, 20, 0, 0, 0, TimeSpan.Zero),
420 | Rating = 4.80,
421 | Location = GeographyPoint.Create(33.84643, -84.362465),
422 | Address = new Address()
423 | {
424 | StreetAddress = "3393 Peachtree Rd",
425 | City = "Atlanta",
426 | StateProvince = "GA",
427 | PostalCode = "30326",
428 | Country = "USA"
429 | },
430 | Rooms = new Room[]
431 | {
432 | new Room()
433 | {
434 | Description = "Standard Room, 2 Queen Beds (Amenities)",
435 | DescriptionFr = "Chambre Standard, 2 grands lits (Services)",
436 | Type = "Standard Room",
437 | BaseRate = 101.99,
438 | BedOptions = "2 Queen Beds",
439 | SleepsCount = 4,
440 | SmokingAllowed = true,
441 | Tags = new[] { "vcr/dvd", "vcr/dvd" }
442 | },
443 | new Room ()
444 | {
445 | Description = "Standard Room, 2 Double Beds (Waterfront View)",
446 | DescriptionFr = "Chambre Standard, 2 lits doubles (vue sur le front de mer)",
447 | Type = "Standard Room",
448 | BaseRate = 106.99,
449 | BedOptions = "2 Double Beds",
450 | SleepsCount = 2,
451 | SmokingAllowed = true,
452 | Tags = new[] { "coffee maker" }
453 | },
454 | new Room()
455 | {
456 | Description = "Deluxe Room, 2 Double Beds (Cityside)",
457 | DescriptionFr = "Chambre Deluxe, 2 lits doubles (Cityside)",
458 | Type = "Budget Room",
459 | BaseRate = 180.99,
460 | BedOptions = "2 Double Beds",
461 | SleepsCount = 2,
462 | SmokingAllowed = true,
463 | Tags = new[] { "suite" }
464 | }
465 | }
466 | }
467 | )
468 | );
469 | try
470 | {
471 | IndexDocumentsResult result = searchClient.IndexDocuments(batch);
472 | }
473 | catch (Exception)
474 | {
475 | // Sometimes when your Search service is under load, indexing will fail for some of the documents in
476 | // the batch. Depending on your application, you can take compensating actions like delaying and
477 | // retrying. For this simple demo, we just log the failed document keys and continue.
478 | Console.WriteLine(
479 | "Failed to index some of the documents: {0}");
480 | }
481 |
482 | Console.WriteLine("Waiting for documents to be indexed...\n");
483 | Thread.Sleep(2000);
484 | }
485 | #endif
486 |
487 | private static void RunQueries(SearchClient searchClient)
488 | {
489 | SearchOptions options;
490 | SearchResults results;
491 |
492 | Console.WriteLine("Search the entire index for the term 'motel' and return only the HotelName field:\n");
493 |
494 | options = new SearchOptions();
495 | options.Select.Add("HotelName");
496 |
497 | results = searchClient.Search("motel", options);
498 |
499 | WriteDocuments(results);
500 |
501 | Console.Write("Apply a filter to the index to find hotels with a room cheaper than $100 per night, ");
502 | Console.WriteLine("and return the hotelId and description:\n");
503 |
504 | options = new SearchOptions()
505 | {
506 | Filter = "Rooms/any(r: r/BaseRate lt 100)"
507 | };
508 | options.Select.Add("HotelId");
509 | options.Select.Add("Description");
510 |
511 | results = searchClient.Search("*", options);
512 |
513 | WriteDocuments(results);
514 |
515 | Console.Write("Search the entire index, order by a specific field (lastRenovationDate) ");
516 | Console.Write("in descending order, take the top two results, and show only hotelName and ");
517 | Console.WriteLine("lastRenovationDate:\n");
518 |
519 | options =
520 | new SearchOptions()
521 | {
522 | Size = 2
523 | };
524 | options.OrderBy.Add("LastRenovationDate desc");
525 | options.Select.Add("HotelName");
526 | options.Select.Add("LastRenovationDate");
527 |
528 | results = searchClient.Search("*", options);
529 |
530 | WriteDocuments(results);
531 |
532 | Console.WriteLine("Search the hotel names for the term 'hotel':\n");
533 |
534 | options = new SearchOptions();
535 | options.SearchFields.Add("HotelName");
536 |
537 | //Adding details to select, because "Location" is not supported yet when deserialize search result to "Hotel"
538 | options.Select.Add("HotelId");
539 | options.Select.Add("HotelName");
540 | options.Select.Add("Description");
541 | options.Select.Add("Category");
542 | options.Select.Add("Tags");
543 | options.Select.Add("ParkingIncluded");
544 | options.Select.Add("LastRenovationDate");
545 | options.Select.Add("Rating");
546 | options.Select.Add("Address");
547 | options.Select.Add("Rooms");
548 |
549 | results = searchClient.Search("hotel", options);
550 |
551 | WriteDocuments(results);
552 | }
553 |
554 | private static void WriteDocuments(SearchResults searchResults)
555 | {
556 | foreach (SearchResult result in searchResults.GetResults())
557 | {
558 | Console.WriteLine(result.Document);
559 | }
560 |
561 | Console.WriteLine();
562 | }
563 | }
564 | }
565 |
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo/Room.Methods.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace AzureSearch.SDKHowTo
5 | {
6 | public partial class Room
7 | {
8 | // This implementation of ToString() is only for the purposes of the sample console application.
9 | // You can override ToString() in your own model class if you want, but you don't need to in order
10 | // to use the Azure Search .NET SDK.
11 | public override string ToString()
12 | {
13 | var builder = new StringBuilder();
14 |
15 | if (!String.IsNullOrEmpty(Description))
16 | {
17 | builder.AppendFormat("Description: {0}\n", Description);
18 | }
19 |
20 | if (!String.IsNullOrEmpty(DescriptionFr))
21 | {
22 | builder.AppendFormat("DescriptionFr: {0}\n", DescriptionFr);
23 | }
24 |
25 | if (!String.IsNullOrEmpty(Type))
26 | {
27 | builder.AppendFormat("Type: {0}\n", Type);
28 | }
29 |
30 | if (BaseRate.HasValue)
31 | {
32 | builder.AppendFormat("BaseRate: {0}\n", BaseRate);
33 | }
34 |
35 | if (!String.IsNullOrEmpty(BedOptions))
36 | {
37 | builder.AppendFormat("BedOptions: {0}\n", BedOptions);
38 | }
39 |
40 | builder.AppendFormat("SleepsCount: {0}\n", BedOptions);
41 |
42 | if (SmokingAllowed.HasValue)
43 | {
44 | builder.AppendFormat("Smoking allowed: {0}\n", SmokingAllowed.Value ? "yes" : "no");
45 | }
46 |
47 | if (Tags != null && Tags.Length > 0)
48 | {
49 | builder.AppendFormat("Tags: [ {0} ]\n", String.Join(", ", Tags));
50 | }
51 |
52 | return builder.ToString();
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo/Room.cs:
--------------------------------------------------------------------------------
1 | using Azure.Search.Documents.Indexes;
2 | using Azure.Search.Documents.Indexes.Models;
3 | using System.Text.Json.Serialization;
4 |
5 | namespace AzureSearch.SDKHowTo
6 | {
7 | public partial class Room
8 | {
9 | [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnMicrosoft)]
10 | public string Description { get; set; }
11 |
12 | [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrMicrosoft)]
13 | [JsonPropertyName("Description_fr")]
14 | public string DescriptionFr { get; set; }
15 |
16 | [SearchableField(IsFilterable = true, IsFacetable = true)]
17 | public string Type { get; set; }
18 |
19 | [SimpleField(IsFilterable = true, IsFacetable = true)]
20 | public double? BaseRate { get; set; }
21 |
22 | [SearchableField(IsFilterable = true, IsFacetable = true)]
23 | public string BedOptions { get; set; }
24 |
25 | [SimpleField(IsFilterable = true, IsFacetable = true)]
26 | public int SleepsCount { get; set; }
27 |
28 | [SimpleField(IsFilterable = true, IsFacetable = true)]
29 | public bool? SmokingAllowed { get; set; }
30 |
31 | [SearchableField(IsFilterable = true, IsFacetable = true)]
32 | public string[] Tags { get; set; }
33 | }
34 | }
--------------------------------------------------------------------------------
/DotNetHowTo/DotNetHowTo/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "SearchServiceEndPoint": "[Put your search service full URL here]",
3 | "SearchIndexName": "hotels",
4 | "SearchServiceAdminApiKey": "[Put your primary or secondary Admin API key here]",
5 | "SearchServiceQueryApiKey": "[Put your primary or secondary Query API key here]"
6 | }
--------------------------------------------------------------------------------
/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26403.7
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{094ACADF-8AB5-491C-ADB4-31C6724EBA5A}") = "DotNetHowToEncryptionUsingCMK", "DotNetHowToEncryptionUsingCMK\DotNetHowToEncryptionUsingCMK.csproj", "{B92A9C7E-DB49-40A1-9DC0-4A235E2D9AB4}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {B92A9C7E-DB49-40A1-9DC0-4A235E2D9AB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {B92A9C7E-DB49-40A1-9DC0-4A235E2D9AB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {B92A9C7E-DB49-40A1-9DC0-4A235E2D9AB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {B92A9C7E-DB49-40A1-9DC0-4A235E2D9AB4}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | PreserveNewest
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Hotel.Methods.cs:
--------------------------------------------------------------------------------
1 | namespace AzureSearch.SDKHowTo
2 | {
3 | using System;
4 | using System.Text;
5 |
6 | public partial class Hotel
7 | {
8 | // This implementation of ToString() is only for the purposes of the sample console application.
9 | // You can override ToString() in your own model class if you want, but you don't need to in order
10 | // to use the Azure Search .NET SDK.
11 | public override string ToString()
12 | {
13 | var builder = new StringBuilder();
14 |
15 | if (!String.IsNullOrEmpty(HotelId))
16 | {
17 | builder.AppendFormat("ID: {0}\t", HotelId);
18 | }
19 |
20 | if (BaseRate.HasValue)
21 | {
22 | builder.AppendFormat("Base rate: {0}\t", BaseRate);
23 | }
24 |
25 | if (!String.IsNullOrEmpty(Description))
26 | {
27 | builder.AppendFormat("Description: {0}\t", Description);
28 | }
29 |
30 | if (!String.IsNullOrEmpty(DescriptionFr))
31 | {
32 | builder.AppendFormat("Description (French): {0}\t", DescriptionFr);
33 | }
34 |
35 | if (!String.IsNullOrEmpty(HotelName))
36 | {
37 | builder.AppendFormat("Name: {0}\t", HotelName);
38 | }
39 |
40 | if (!String.IsNullOrEmpty(Category))
41 | {
42 | builder.AppendFormat("Category: {0}\t", Category);
43 | }
44 |
45 | if (Tags != null && Tags.Length > 0)
46 | {
47 | builder.AppendFormat("Tags: [{0}]\t", String.Join(", ", Tags));
48 | }
49 |
50 | if (ParkingIncluded.HasValue)
51 | {
52 | builder.AppendFormat("Parking included: {0}\t", ParkingIncluded.Value ? "yes" : "no");
53 | }
54 |
55 | if (SmokingAllowed.HasValue)
56 | {
57 | builder.AppendFormat("Smoking allowed: {0}\t", SmokingAllowed.Value ? "yes" : "no");
58 | }
59 |
60 | if (LastRenovationDate.HasValue)
61 | {
62 | builder.AppendFormat("Last renovated on: {0}\t", LastRenovationDate);
63 | }
64 |
65 | if (Rating.HasValue)
66 | {
67 | builder.AppendFormat("Rating: {0}/5\t", Rating);
68 | }
69 |
70 | if (Location != null)
71 | {
72 | builder.AppendFormat("Location: Latitude {0}, longitude {1}\t", Location.Latitude, Location.Longitude);
73 | }
74 |
75 | return builder.ToString();
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Hotel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Spatial;
3 | using Azure.Search.Documents.Indexes;
4 | using Azure.Search.Documents.Indexes.Models;
5 | using System.Text.Json.Serialization;
6 |
7 | namespace AzureSearch.SDKHowTo
8 | {
9 |
10 |
11 | // The JsonPropertyName attribute is defined in the Azure Search .NET SDK.
12 | // Here it used to ensure that Pascal-case property names in the model class are mapped to camel-case
13 | // field names in the index.
14 | public partial class Hotel
15 | {
16 | [SimpleField(IsKey = true, IsFilterable = true)]
17 | public string HotelId { get; set; }
18 |
19 | [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
20 | public double? BaseRate { get; set; }
21 |
22 | [SearchableField]
23 | public string Description { get; set; }
24 |
25 | [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)]
26 | public string DescriptionFr { get; set; }
27 |
28 | [SearchableField(IsFilterable = true, IsSortable = true)]
29 | public string HotelName { get; set; }
30 |
31 | [SearchableField(IsFilterable = true, IsFacetable = true, IsSortable = true)]
32 | public string Category { get; set; }
33 |
34 | [SearchableField(IsFilterable = true, IsFacetable = true)]
35 | public string[] Tags { get; set; }
36 |
37 | [SimpleField(IsFilterable = true, IsFacetable = true)]
38 | public bool? ParkingIncluded { get; set; }
39 |
40 | [SimpleField(IsFilterable = true, IsFacetable = true)]
41 | public bool? SmokingAllowed { get; set; }
42 |
43 | [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
44 | public DateTimeOffset? LastRenovationDate { get; set; }
45 |
46 | [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
47 | public int? Rating { get; set; }
48 |
49 | [SimpleField(IsFilterable = true, IsSortable = true)]
50 | public GeographyPoint Location { get; set; }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Program.cs:
--------------------------------------------------------------------------------
1 | #define HowToExample
2 |
3 | using System;
4 | using System.Linq;
5 | using System.Threading;
6 | using Azure;
7 | using Azure.Search.Documents;
8 | using Azure.Search.Documents.Indexes;
9 | using Azure.Search.Documents.Indexes.Models;
10 | using Azure.Search.Documents.Models;
11 | using Microsoft.Extensions.Configuration;
12 | using Microsoft.Spatial;
13 |
14 | namespace AzureSearch.SDKHowTo
15 | {
16 | class Program
17 | {
18 | // This sample shows how to create a synonym-map and an index that are encrypted with customer-managed key in Azure Key Vault
19 | static void Main(string[] args)
20 | {
21 | IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
22 | IConfigurationRoot configuration = builder.Build();
23 |
24 | SearchIndexClient indexClient = CreateSearchIndexClient(configuration);
25 |
26 | Console.WriteLine("Cleaning up resources...\n");
27 | CleanupResources(indexClient);
28 |
29 | Console.WriteLine("Creating synonym-map encrypted with customer managed key...\n");
30 | CreateSynonymsEncryptedUsingCustomerManagedKey(indexClient, configuration);
31 |
32 | Console.WriteLine("Creating index encrypted with customer managed key...\n");
33 | CreateHotelsIndexEncryptedUsingCustomerManagedKey(indexClient, configuration);
34 |
35 | SearchIndex index = indexClient.GetIndex("hotels");
36 | index = AddSynonymMapsToFields(index);
37 | indexClient.CreateOrUpdateIndex(index);
38 |
39 | SearchClient searchClient = indexClient.GetSearchClient("hotels");
40 |
41 | Console.WriteLine("Uploading documents...\n");
42 | UploadDocuments(searchClient);
43 |
44 | SearchClient searchClientForQueries = CreateSearchClient(configuration);
45 |
46 | RunQueries(searchClientForQueries);
47 |
48 | Console.WriteLine("Complete. Press any key to end application...\n");
49 | Console.ReadKey();
50 | }
51 |
52 | private static SearchIndexClient CreateSearchIndexClient(IConfigurationRoot configuration)
53 | {
54 | string searchServiceEndPoint = configuration["SearchServiceEndPoint"];
55 | string adminApiKey = configuration["SearchServiceAdminApiKey"];
56 |
57 | SearchIndexClient indexClient = new SearchIndexClient(new Uri(searchServiceEndPoint), new AzureKeyCredential(adminApiKey));
58 | return indexClient;
59 | }
60 |
61 | private static SearchClient CreateSearchClient(IConfigurationRoot configuration)
62 | {
63 | string searchServiceEndPoint = configuration["SearchServiceEndPoint"];
64 | string queryApiKey = configuration["SearchServiceQueryApiKey"];
65 |
66 | SearchClient searchClient = new SearchClient(new Uri(searchServiceEndPoint), "hotels", new AzureKeyCredential(queryApiKey));
67 | return searchClient;
68 | }
69 |
70 | private static void CleanupResources(SearchIndexClient indexClient)
71 | {
72 | try
73 | {
74 | if (indexClient.GetIndex("hotels") != null)
75 | {
76 | indexClient.DeleteIndex("hotels");
77 | }
78 | if (indexClient.GetSynonymMapNames().Value.Contains("desc-synonymmap"))
79 | {
80 | indexClient.DeleteSynonymMap("desc-synonymmap");
81 | }
82 | }
83 | catch (RequestFailedException e) when (e.Status == 404)
84 | {
85 | //if exception occurred and status is "Not Found", this is work as expect
86 | Console.WriteLine("Failed to find index and this is because it's not there.");
87 | }
88 | }
89 |
90 | private static void CreateSynonymsEncryptedUsingCustomerManagedKey(SearchIndexClient indexClient, IConfigurationRoot configuration)
91 | {
92 | var synonymMap = new SynonymMap("desc-synonymmap", "hotel, motel\ninternet,wifi\nfive star=>luxury\neconomy,inexpensive=>budget")
93 | {
94 | EncryptionKey = GetEncryptionKeyFromConfiguration(configuration)
95 | };
96 |
97 | indexClient.CreateOrUpdateSynonymMap(synonymMap);
98 | }
99 |
100 | private static SearchIndex AddSynonymMapsToFields(SearchIndex index)
101 | {
102 | //remove SynonymMaps attribute in class hotel, need Add maps manually.
103 | index.Fields.First(f => f.Name == "Category").SynonymMapNames.Add("desc-synonymmap");
104 | index.Fields.First(f => f.Name == "Tags").SynonymMapNames.Add("desc-synonymmap");
105 | return index;
106 | }
107 |
108 | private static void CreateHotelsIndexEncryptedUsingCustomerManagedKey(SearchIndexClient indexClient, IConfigurationRoot configuration)
109 | {
110 | FieldBuilder fieldBuilder = new FieldBuilder();
111 | var searchFields = fieldBuilder.Build(typeof(Hotel));
112 | var definition = new SearchIndex("hotels", searchFields)
113 | {
114 | EncryptionKey = GetEncryptionKeyFromConfiguration(configuration)
115 | };
116 |
117 | indexClient.CreateOrUpdateIndex(definition);
118 | }
119 |
120 | private static SearchResourceEncryptionKey GetEncryptionKeyFromConfiguration(IConfigurationRoot configuration)
121 | {
122 | Uri keyVaultKeyUri = new Uri(configuration["AzureKeyVaultKeyIdentifier"]);
123 |
124 | if (!keyVaultKeyUri.Host.Contains("vault.azure.net") || keyVaultKeyUri.Segments.Length != 4 || keyVaultKeyUri.Segments[1] != "keys/")
125 | {
126 | throw new ArgumentException("Invalid 'AzureKeyVaultKeyIdentifier' - Expected format: 'https://.vault.azure.net/keys//'", "AzureKeyVaultKeyIdentifier");
127 | }
128 |
129 | SearchResourceEncryptionKey encryptionKey = null;
130 | string applicationId = configuration["AzureActiveDirectoryApplicationId"];
131 | if (!string.IsNullOrWhiteSpace(applicationId))
132 | {
133 | encryptionKey = new SearchResourceEncryptionKey(new Uri($"{keyVaultKeyUri.Scheme}://{keyVaultKeyUri.Host}"), keyVaultKeyUri.Segments[2].Trim('/'), keyVaultKeyUri.Segments[3].Trim('/'))
134 | {
135 | ApplicationId = applicationId,
136 | ApplicationSecret = configuration["AzureActiveDirectoryApplicationSecret"]
137 | };
138 | }
139 |
140 |
141 | return encryptionKey;
142 | }
143 |
144 | private static void UploadDocuments(SearchClient searchClient)
145 | {
146 | IndexDocumentsBatch batch = IndexDocumentsBatch.Create(
147 | IndexDocumentsAction.Upload(
148 | new Hotel()
149 | {
150 | HotelId = "1",
151 | BaseRate = 199.0,
152 | Description = "Best hotel in town",
153 | DescriptionFr = "Meilleur hôtel en ville",
154 | HotelName = "Fancy Stay",
155 | Category = "Luxury",
156 | Tags = new[] { "pool", "view", "wifi", "concierge" },
157 | ParkingIncluded = false,
158 | SmokingAllowed = false,
159 | LastRenovationDate = new DateTimeOffset(2010, 6, 27, 0, 0, 0, TimeSpan.Zero),
160 | Rating = 5,
161 | Location = GeographyPoint.Create(47.678581, -122.131577)
162 | }),
163 | IndexDocumentsAction.Upload(
164 | new Hotel()
165 | {
166 | HotelId = "2",
167 | BaseRate = 79.99,
168 | Description = "Cheapest hotel in town",
169 | DescriptionFr = "Hôtel le moins cher en ville",
170 | HotelName = "Roach Motel",
171 | Category = "Budget",
172 | Tags = new[] { "motel", "budget" },
173 | ParkingIncluded = true,
174 | SmokingAllowed = true,
175 | LastRenovationDate = new DateTimeOffset(1982, 4, 28, 0, 0, 0, TimeSpan.Zero),
176 | Rating = 1,
177 | Location = GeographyPoint.Create(49.678581, -122.131577)
178 | }));
179 | try
180 | {
181 | IndexDocumentsResult result = searchClient.IndexDocuments(batch);
182 | }
183 | catch (Exception)
184 | {
185 | // Sometimes when your Search service is under load, indexing will fail for some of the documents in
186 | // the batch. Depending on your application, you can take compensating actions like delaying and
187 | // retrying. For this simple demo, we just log the failed document keys and continue.
188 | Console.WriteLine("Failed to index some of the documents: {0}");
189 | }
190 |
191 | Console.WriteLine("Waiting for documents to be indexed...\n");
192 | Thread.Sleep(2000);
193 | }
194 |
195 | private static void RunQueries(SearchClient searchClient)
196 | {
197 | SearchOptions searchOptions;
198 | SearchResults results;
199 |
200 | Console.WriteLine("Search with terms nonexistent in the index:\n");
201 |
202 | searchOptions = new SearchOptions();
203 | searchOptions.SearchFields.Add("Category");
204 | searchOptions.SearchFields.Add("Tags");
205 | searchOptions.Select.Add("HotelName");
206 | searchOptions.Select.Add("Category");
207 | searchOptions.Select.Add("Tags");
208 |
209 | Console.WriteLine("Search the entire index for the phrase \"five star\":\n");
210 | results = searchClient.Search("\"five star\"", searchOptions);
211 | WriteDocuments(results);
212 |
213 | Console.WriteLine("Search the entire index for the term 'internet':\n");
214 | results = searchClient.Search("internet", searchOptions);
215 | WriteDocuments(results);
216 |
217 | Console.WriteLine("Search the entire index for the terms 'economy' AND 'hotel':\n");
218 | results = searchClient.Search("economy AND hotel", searchOptions);
219 | WriteDocuments(results);
220 | }
221 |
222 | private static void WriteDocuments(SearchResults searchResults)
223 | {
224 | foreach (SearchResult result in searchResults.GetResults())
225 | {
226 | Console.WriteLine(result.Document);
227 | }
228 |
229 | Console.WriteLine();
230 | }
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "SearchServiceEndpoint": "Search service URL goes here",
3 | "SearchServiceAdminApiKey": "Search service Admin API key goes here",
4 | "SearchServiceQueryApiKey": "Search service query API key goes here",
5 | "AzureKeyVaultKeyIdentifier": "Azure Key Vault key URL goes here. Expected format: 'https://.vault.azure.net/keys//'",
6 | "AzureActiveDirectoryApplicationId": "Azure AD Application ID (not to be confused with Object ID or Tenant ID). Make sure this application has an Access Policy set up in Azure Key Vault.",
7 | "AzureActiveDirectoryApplicationSecret": "Azure AD authentication key found in Certificates and Secrets."
8 | }
9 |
--------------------------------------------------------------------------------
/DotNetHowToIndexers/DotNetHowToIndexers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | 7.1
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | PreserveNewest
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/DotNetHowToIndexers/DotNetHowToIndexers.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27004.2002
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetHowToIndexers", "DotNetHowToIndexers.csproj", "{BF3D2EEE-21FF-41B9-8693-378112D91849}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {BF3D2EEE-21FF-41B9-8693-378112D91849}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {BF3D2EEE-21FF-41B9-8693-378112D91849}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {BF3D2EEE-21FF-41B9-8693-378112D91849}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {BF3D2EEE-21FF-41B9-8693-378112D91849}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {E143772B-7C24-4039-8BAB-F30E4A628D8F}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/DotNetHowToIndexers/Hotel.cs:
--------------------------------------------------------------------------------
1 | using Azure.Search.Documents.Indexes;
2 | using Azure.Search.Documents.Indexes.Models;
3 | using Microsoft.Spatial;
4 | using System;
5 | using System.Text.Json.Serialization;
6 |
7 | namespace AzureSearch.SDKHowTo
8 | {
9 |
10 |
11 | // The JsonPropertyName attribute is defined in the Azure Search .NET SDK.
12 | // Here it used to ensure that Pascal-case property names in the model class are mapped to camel-case
13 | // field names in the index.
14 | public partial class Hotel
15 | {
16 | [SimpleField(IsKey = true, IsFilterable = true)]
17 | [JsonPropertyName("hotelId")]
18 | public string HotelId { get; set; }
19 |
20 | [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
21 | [JsonPropertyName("baseRate")]
22 | public double? BaseRate { get; set; }
23 |
24 | [SearchableField]
25 | [JsonPropertyName("description")]
26 | public string Description { get; set; }
27 |
28 | [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)]
29 | [JsonPropertyName("description_fr")]
30 | public string DescriptionFr { get; set; }
31 |
32 | [SearchableField(IsFilterable = true, IsSortable = true)]
33 | [JsonPropertyName("hotelName")]
34 | public string HotelName { get; set; }
35 |
36 | [SearchableField(IsFilterable = true, IsFacetable = true, IsSortable = true)]
37 | [JsonPropertyName("category")]
38 | public string Category { get; set; }
39 |
40 | [SearchableField(IsFilterable = true, IsFacetable = true)]
41 | [JsonPropertyName("tags")]
42 | public string[] Tags { get; set; }
43 |
44 | [SimpleField(IsFilterable = true, IsFacetable = true)]
45 | [JsonPropertyName("parkingIncluded")]
46 | public bool? ParkingIncluded { get; set; }
47 |
48 | [SimpleField(IsFilterable = true, IsFacetable = true)]
49 | [JsonPropertyName("smokingAllowed")]
50 | public bool? SmokingAllowed { get; set; }
51 |
52 | [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
53 | [JsonPropertyName("lastRenovationDate")]
54 | public DateTimeOffset? LastRenovationDate { get; set; }
55 |
56 | [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
57 | [JsonPropertyName("rating")]
58 | public int? Rating { get; set; }
59 |
60 | [SimpleField(IsFilterable = true, IsSortable = true)]
61 | [FieldBuilderIgnore]
62 | [JsonPropertyName("location")]
63 | public GeographyPoint Location { get; set; }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/DotNetHowToIndexers/Program.cs:
--------------------------------------------------------------------------------
1 | using Azure;
2 | using Azure.Search.Documents.Indexes;
3 | using Azure.Search.Documents.Indexes.Models;
4 | using Microsoft.Extensions.Configuration;
5 | using System;
6 | using System.Threading.Tasks;
7 |
8 |
9 | namespace AzureSearch.SDKHowTo
10 | {
11 | ///
12 | /// Demo of Azure Search indexer for Azure SQL
13 | ///
14 | public sealed class Program
15 | {
16 | public static async Task Main(string[] args)
17 | {
18 | IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
19 | IConfigurationRoot configuration = builder.Build();
20 |
21 | if (configuration["SearchServiceEndPoint"] == "Put your search service endpoint here")
22 | {
23 | Console.Error.WriteLine("Specify SearchServiceEndPoint in appsettings.json");
24 | Environment.Exit(-1);
25 | }
26 |
27 | if (configuration["SearchServiceAdminApiKey"] == "Put your search service admin API key here")
28 | {
29 | Console.Error.WriteLine("Specify SearchServiceAdminApiKey in appsettings.json");
30 | Environment.Exit(-1);
31 | }
32 |
33 | if (configuration["AzureSQLConnectionString"] == "Put your Azure SQL database connection string here")
34 | {
35 | Console.Error.WriteLine("Specify AzureSQLConnectionString in appsettings.json");
36 | Environment.Exit(-1);
37 | }
38 |
39 | SearchIndexClient indexClient = new SearchIndexClient(new Uri(configuration["SearchServiceEndPoint"]), new AzureKeyCredential(configuration["SearchServiceAdminApiKey"]));
40 | SearchIndexerClient indexerClient = new SearchIndexerClient(new Uri(configuration["SearchServiceEndPoint"]), new AzureKeyCredential(configuration["SearchServiceAdminApiKey"]));
41 |
42 | Console.WriteLine("Creating index...");
43 | FieldBuilder fieldBuilder = new FieldBuilder();
44 | var searchFields = fieldBuilder.Build(typeof(Hotel));
45 | var searchIndex = new SearchIndex("hotels-sql-idx", searchFields);
46 |
47 | // If we have run the sample before, this index will be populated
48 | // We can clear the index by deleting it if it exists and creating
49 | // it again
50 | CleanupSearchIndexClientResources(indexClient, searchIndex);
51 |
52 | indexClient.CreateOrUpdateIndex(searchIndex);
53 |
54 | Console.WriteLine("Creating data source...");
55 |
56 | // The sample data set has a table name of "hotels"
57 | // The sample data set table has a "soft delete" column named IsDeleted
58 | // When this column is set to true and the indexer sees it, it will remove the
59 | // corresponding document from the search service
60 | // See this link for more information
61 | // https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.search.models.softdeletecolumndeletiondetectionpolicy
62 | // The sample data set uses SQL integrated change tracking for change detection
63 | // This means that when the indexer runs, it will be able to detect which data has
64 | // changed since the last run using built in change tracking
65 | // See this link for more information
66 | // https://docs.microsoft.com/en-us/sql/relational-databases/track-changes/about-change-tracking-sql-server
67 | var dataSource =
68 | new SearchIndexerDataSourceConnection(
69 | "hotels-sql-ds",
70 | SearchIndexerDataSourceType.AzureSql,
71 | configuration["AzureSQLConnectionString"],
72 | new SearchIndexerDataContainer("hotels"));
73 |
74 | // The data source does not need to be deleted if it was already created,
75 | // but the connection string may need to be updated if it was changed
76 | indexerClient.CreateOrUpdateDataSourceConnection(dataSource);
77 |
78 | Console.WriteLine("Creating Azure SQL indexer...");
79 |
80 | var schedule = new IndexingSchedule(TimeSpan.FromDays(1))
81 | {
82 | StartTime = DateTimeOffset.Now
83 | };
84 |
85 | var parameters = new IndexingParameters()
86 | {
87 | BatchSize = 100,
88 | MaxFailedItems = 0,
89 | MaxFailedItemsPerBatch = 0
90 | };
91 |
92 | // Indexer declarations require a data source and search index.
93 | // Common optional properties include a schedule, parameters, and field mappings
94 | // The field mappings below are redundant due to how the Hotel class is defined, but
95 | // we included them anyway to show the syntax
96 | var indexer = new SearchIndexer("hotels-sql-idxr", dataSource.Name, searchIndex.Name)
97 | {
98 | Description = "Data indexer",
99 | Schedule = schedule,
100 | Parameters = parameters,
101 | FieldMappings =
102 | {
103 | new FieldMapping("_id") {TargetFieldName = "HotelId"},
104 | new FieldMapping("Amenities") {TargetFieldName = "Tags"}
105 | }
106 | };
107 |
108 | // Indexers contain metadata about how much they have already indexed
109 | // If we already ran the sample, the indexer will remember that it already
110 | // indexed the sample data and not run again
111 | // To avoid this, reset the indexer if it exists
112 | CleanupSearchIndexerClientResources(indexerClient, indexer);
113 |
114 | await indexerClient.CreateOrUpdateIndexerAsync(indexer);
115 |
116 | // We created the indexer with a schedule, but we also
117 | // want to run it immediately
118 | Console.WriteLine("Running Azure SQL indexer...");
119 |
120 | try
121 | {
122 | await indexerClient.RunIndexerAsync(indexer.Name);
123 | }
124 | catch (RequestFailedException ex) when (ex.Status == 429)
125 | {
126 | Console.WriteLine("Failed to run indexer: {0}", ex.Message);
127 | }
128 |
129 | // Wait 5 seconds for indexing to complete before checking status
130 | Console.WriteLine("Waiting for indexing...\n");
131 | System.Threading.Thread.Sleep(5000);
132 |
133 | // After an indexer run, you can retrieve status.
134 | CheckIndexerStatus(indexerClient, indexer);
135 |
136 | Console.WriteLine("Press any key to continue...");
137 | Console.ReadKey();
138 | Environment.Exit(0);
139 | }
140 |
141 | private static void CheckIndexerStatus(SearchIndexerClient indexerClient, SearchIndexer indexer)
142 | {
143 | try
144 | {
145 | string indexerName = "hotels-sql-idxr";
146 | SearchIndexerStatus execInfo = indexerClient.GetIndexerStatus(indexerName);
147 |
148 | Console.WriteLine("Indexer has run {0} times.", execInfo.ExecutionHistory.Count);
149 | Console.WriteLine("Indexer Status: " + execInfo.Status.ToString());
150 |
151 | IndexerExecutionResult result = execInfo.LastResult;
152 |
153 | Console.WriteLine("Latest run");
154 | Console.WriteLine("Run Status: {0}", result.Status.ToString());
155 | Console.WriteLine("Total Documents: {0}, Failed: {1}", result.ItemCount, result.FailedItemCount);
156 |
157 | //TimeSpan elapsed = result.EndTime.Value - result.StartTime.Value;
158 | //Console.WriteLine("StartTime: {0:T}, EndTime: {1:T}, Elapsed: {2:t}", result.StartTime.Value, result.EndTime.Value, elapsed);
159 |
160 | string errorMsg = (result.ErrorMessage == null) ? "none" : result.ErrorMessage;
161 | Console.WriteLine("ErrorMessage: {0}", errorMsg);
162 | Console.WriteLine(" Document Errors: {0}, Warnings: {1}\n", result.Errors.Count, result.Warnings.Count);
163 | }
164 | catch (RequestFailedException ex) when (ex.Status == 429)
165 | {
166 | Console.WriteLine("Failed to run indexer check: {0}", ex.Message);
167 | }
168 | }
169 |
170 | private static void CleanupSearchIndexClientResources(SearchIndexClient indexClient, SearchIndex index)
171 | {
172 | try
173 | {
174 | if (indexClient.GetIndex(index.Name) != null)
175 | {
176 | indexClient.DeleteIndex(index.Name);
177 | }
178 | }
179 | catch (RequestFailedException e) when (e.Status == 404)
180 | {
181 | //if exception occurred and status is "Not Found", this is working as expected
182 | Console.WriteLine("If an index of the same name is detected, it's deleted now so that we can reuse the name.");
183 | }
184 | }
185 |
186 | private static void CleanupSearchIndexerClientResources(SearchIndexerClient indexerClient, SearchIndexer indexer)
187 | {
188 | try
189 | {
190 | if (indexerClient.GetIndexer(indexer.Name) != null)
191 | {
192 | indexerClient.ResetIndexer(indexer.Name);
193 | }
194 | }
195 | catch (RequestFailedException ex) when (ex.Status == 404)
196 | {
197 | //if exception occurred and status is "Not Found", this is working as expected
198 | Console.WriteLine("The indexer doesn't exist.");
199 | }
200 | }
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/DotNetHowToIndexers/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "SearchServiceEndPoint": "Put your search service EndPoint here",
3 | "SearchServiceAdminApiKey": "Put your primary or secondary API key here",
4 | "AzureSQLConnectionString": "Put your Azure SQL database connection string here"
5 | }
6 |
--------------------------------------------------------------------------------
/DotNetHowToIndexers/hotels.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/search-dotnet-getting-started/1783e951291d9be8d198eb27a4c82f3f074b629a/DotNetHowToIndexers/hotels.sql
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Microsoft Corporation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | page_type: sample
3 | description: "Contains several projects to help you get started with Azure AI Search and the .NET SDK"
4 | languages:
5 | - csharp
6 | products:
7 | - azure
8 | - azure-cognitive-search
9 | ---
10 |
11 | # Getting Started with Azure AI Search using .NET
12 |
13 | This repository includes several projects that show you how to use the [**Azure.Search.Documents**](https://docs.microsoft.com/dotnet/api/overview/azure/search.documents-readme) client library in Azure SDK for .NET to create C# applications that use Azure AI Search.
14 |
15 | An earlier version of the samples that were built using the [**Microsoft.Azure.Search**](https://docs.microsoft.com/dotnet/api/overview/azure/search/client10) client libraries can be found in the **v10** branch of this repo. To download those versions, switch the branch from **master** to **v10**, and then select **Code** to download or open those samples.
16 |
17 | ## DotNetHowTo
18 |
19 | This sample is a simple .NET Core console application that shows you how to:
20 |
21 | * Create and delete a search index
22 | * Upload documents
23 | * Search and filter documents within an index
24 |
25 | To run this sample, open the solution in Visual Studio and modify **appsettings.json** to use valid values for your search service.
26 |
27 |
28 |
29 | ## DotNetHowToEncryptionUsingCMK
30 |
31 | This sample demonstrates how to create a synonym-map and an index that are encrypted with a customer-managed key in Azure Key Vault. This sample uses several services that must be set up in advance: Azure Key Vault, Azure Active Directory, and modifications to your existing search service.
32 |
33 | The **appsettings.json** file provides placeholders for service information.
34 |
35 | For detailed instructions, see [How to configure customer-managed keys for data encryption in Azure AI Search](https://docs.microsoft.com/azure/search/search-security-manage-encryption-keys).
36 |
37 | ## DotNetHowToIndexers
38 |
39 | This sample is a simple .NET Core console application that shows how create and run a search indexer that retrieves data from an Azure SQL database.
40 |
41 | Before you can run this sample, you will need an Azure SQL database that contains sample data used by the indexer. You will also need to modify settings in **appsettings.json**.
42 |
43 | 1. Create a new database in Azure SQL named hotels.
44 | 1. Run the `data\hotels.sql` script provided in this sample against your Azure SQL database.
45 | 1. Open the DotNetHowToIndexers.sln in Visual Studio.
46 | 1. Update the appsettings.json with your service name, api key, and connection string to your Azure SQL database.
47 | 1. Compile and Run the project using Visual Studio.
48 |
49 | ## Retired samples
50 |
51 | The following samples have been removed from the master branch.
52 |
53 | ### DotNetETagsExplainer
54 |
55 | This sample is [now archived](https://github.com/Azure-Samples/azure-search-sample-archive). It's a .console application that shows how to use ETags to update Azure AI Search resources safely in the presence of concurrency. The code in this sample simulates concurrent write operations so that you can see how that condition is handled.
56 |
57 | ### DotNetHowToSecurityTrimming (Archived)
58 |
59 | This sample is [now archived](https://github.com/Azure-Samples/azure-search-sample-archive). It's replaced by [instructions for setting up access control](https://github.com/Azure-Samples/azure-search-openai-demo/blob/main/LoginAndAclSetup.md) on the [azure-search-openai-demo](https://github.com/Azure-Samples/azure-search-openai-demo/tree/main).
60 |
61 | ### DotNetHowToSynonyms (Archived)
62 |
63 | This C# sample was used to demonstrate the benefits of adding a synonym map using "before-and-after" queries. The Azure SDK team provides a more recent sample. See [Azure.Search.Documents Samples - Service Operations](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/search/Azure.Search.Documents/samples/Sample02_Service.md#create-a-synonym-map) for replacement code.
64 |
65 | ### DotNetHowToAutocomplete
66 |
67 | This sample was not migrated to use the Azure.Search.Documents client library. It has been replaced by a project in the [create-first-app](https://github.com/Azure-Samples/azure-search-dotnet-samples/tree/master/create-first-app) sample in the [azure-search-dotnet-samples](https://github.com/Azure-Samples/azure-search-dotnet-samples) repository. Alternatively, you can look at the v10 version of the sample.
68 |
69 | ### DotNetHowToMultipleDataSources
70 |
71 | This sample was not migrated to use the Azure.Search.Documents client library. It has been replaced by the [multiple-data-sources](https://github.com/Azure-Samples/azure-search-dotnet-samples/tree/master/multiple-data-sources) sample in the [azure-search-dotnet-samples](https://github.com/Azure-Samples/azure-search-dotnet-samples) repository. Alternatively, you can look at the v10 version of the sample.
72 |
73 | ### DotNetSample
74 |
75 | This sample was not migrated to use the Azure.Search.Documents client library. We recommend that you refer to **DotNetHowToIndexers** to view code that calls the Azure SQL Indexer. Alternatively, you can look at the v10 version of the sample.
76 |
77 | ---
78 |
79 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
--------------------------------------------------------------------------------