Skip to content

Commit 80a5a58

Browse files
fixing search api tests; finishing search api readme
1 parent 09cf628 commit 80a5a58

File tree

3 files changed

+124
-67
lines changed

3 files changed

+124
-67
lines changed

.github/README.md

Lines changed: 120 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Browser-compiled script and type definitions can be found in a v2 [dist](https:/
2222

2323
## Main Features
2424

25-
- **Microsoft Dataverse Search API**. Access the full power of its Search, Suggestion and Autocomplete capabilities.
25+
- **Microsoft Dataverse Search API**. Access the full power of its Search (Query), Suggestion and Autocomplete capabilities.
2626
- **Batch Requests**. Convert all requests into a Batch operation with two lines of code.
2727
- **Simplicity and Automation**. Such as automated paging, big file downloading/uploading in chunks of data, automated conversion of requests with long URLs into a Batch Request in the background and more!
2828
- **CRUD operations**. Including Fetch XML, Actions and Functions in Microsoft Dataverse Web API.
@@ -47,7 +47,8 @@ Also, please check [suggestions and contributions](#contributions) section to le
4747

4848
Check out [Dataverse Terminology](https://learn.microsoft.com/en-us/power-apps/developer/data-platform/understand-terminology). Microsoft has done some changes in the namings of the objects and components of D365 and since DynamicsWebApi has been developing for many years there may be _conflicting_ naming, such as: `createEntity` - which _right now_ means "Create a Table Definition". Dataverse SDK terminology is what the library has been based on. I have no plans on changing that (except in documentation), mainly because Microsoft may change the namings again in the future which will lead to naming issues ...again.
4949

50-
**Please note!** "Dynamics 365" in this readme refers to Microsoft Dataverse (formerly known as Microsoft Common Data Service) / Microsoft Dynamics 365 Customer Engagement / Micorosft Dynamics CRM. **NOT** Microsoft Dynamics 365 Finance and Operations.
50+
> [!NOTE]
51+
> "Dynamics 365" in this readme refers to Microsoft Dataverse (formerly known as Microsoft Common Data Service) / Microsoft Dynamics 365 Customer Engagement / Micorosft Dynamics CRM. **NOT** Microsoft Dynamics 365 Finance and Operations.
5152
5253
## Table of Contents
5354

@@ -2163,7 +2164,7 @@ const isDeleted = await dynamicsWebApi.deleteRecord({
21632164
21642165
DynamicsWebApi can be used to call Dataverse Search API and utilize its powerful Query, Suggest and Autocomplete capabilities. Before using, I highly recommend to get familiar with it by reading an [official documentation](https://learn.microsoft.com/en-us/power-apps/developer/data-platform/search/overview?tabs=webapi).
21652166
2166-
**Important!** This documentation is based on the Dataverse Search API v2.0. If you would like to find documentation about v1.0, please check [here](https://github.com/AleksandrRogov/DynamicsWebApi/blob/v2.2.1/.github/README.md#work-with-dataverse-search-api). But keep in mind, that some properties in the request and response objects are marked as deprecated to encourage usage of the v2.0 properties. Deprecated properties will be removed in the next major version.
2167+
**Important!** This documentation is based on the Dataverse Search API v2.0 (added in `v2.3.0`). If you would like to find documentation for v1.0, please check [here](https://github.com/AleksandrRogov/DynamicsWebApi/blob/v2.2.1/.github/README.md#work-with-dataverse-search-api). Just keep in mind, that some properties in the request and response objects are marked as deprecated to encourage usage of the v2.0 properties. Deprecated properties and requests will be removed in the next major version.
21672168
21682169
To set a Search API version use: `new DynamicsWebApi({ searchApi: { version: "2.0" }})`.
21692170
@@ -2225,36 +2226,58 @@ result = await dynamicsWebApi.query("<search term>");
22252226
```
22262227
22272228
```ts
2228-
//more complex example (from Microsoft's documentation)
2229+
//more complex example (from Microsoft's official documentation)
22292230

22302231
const result = await dynamicsWebApi.query({
2231-
search: "Contoso",
2232-
skip: 0,
2233-
top: 7,
2234-
entities: [{
2235-
name: "account",
2236-
selectColumns: ["name", "createdon"],
2237-
searchColumns: ["name"],
2238-
filter: "statecode eq 0"
2239-
}, {
2240-
name: "contact",
2241-
selectColumns: ["fullname", "createdon"],
2242-
searchColumns: ["fullname"],
2243-
filter: "statecode eq 0"
2244-
}],
2245-
orderBy: ["createdon desc"],
2246-
filter: "createdon gt 2022-08-15",
2247-
count: true
2232+
query: {
2233+
search: "Contoso",
2234+
skip: 0,
2235+
top: 7,
2236+
entities: [{
2237+
name: "account",
2238+
selectColumns: ["name", "createdon"],
2239+
searchColumns: ["name"],
2240+
filter: "statecode eq 0"
2241+
}, {
2242+
name: "contact",
2243+
selectColumns: ["fullname", "createdon"],
2244+
searchColumns: ["fullname"],
2245+
filter: "statecode eq 0"
2246+
}],
2247+
orderBy: ["createdon desc"],
2248+
filter: "createdon gt 2022-08-15",
2249+
count: true
2250+
}
22482251
});
22492252

2250-
//result:
2251-
const error = result.Error;
2252-
const value = result.Value;
2253+
//all data for v2 is returned inside the "response" property
2254+
const { Value: value, Error: error } = result.response;
2255+
2256+
console.log("Total records found: ", result.response.Count);
2257+
2258+
if (!error && value.length) {
2259+
//very sophisticated processing of search results :)
2260+
const entityId = value[0].Id;
2261+
const entityName = value[0].EntityName;
2262+
2263+
//entity here is "kind of" entity, it may have more helpful attributes
2264+
const entity = value[0].Attributes;
22532265

2254-
const firstItemId = value[0].Id;
2255-
const firstItemEntityName = value[0].EntityName;
2266+
if (entityName === "account") {
2267+
const accountName = entity.name;
2268+
const objectTypeCode = entity["@search.objecttypecode"]; //0
2269+
} else {
2270+
const contactFullname = entity.fullname;
2271+
const objectTypeCode = entity["@search.objecttypecode"]; //2
2272+
}
2273+
2274+
//etc
2275+
}
22562276
```
22572277
2278+
As you can see all objects are automatically converted and encoded as per official documentation, simplifying developer's
2279+
work to construct the request and to process the response.
2280+
22582281
### Suggest
22592282
22602283
The following table describes all parameters for a `suggest` request:
@@ -2265,46 +2288,77 @@ search | `string` | **Required**. The text to search with. Search term must be a
22652288
entities | `string`, `string[]` or `SearchEntity[]` | Limits the scope of search to a subset of tables. The default set is configured by your administrator when Dataverse search is enabled.
22662289
filter | `string` | Limits the scope of the search results returned.
22672290
fuzzy | `boolean` | Use fuzzy search to aid with misspellings. The default is false.
2268-
options | `string` or `SuggestionOptions` | Options are settings configured to search a search term.
2291+
options | `string` or `SuggestOptions` | Options are settings configured to search a search term.
22692292
orderBy | `string[]` | A list of comma-separated clauses where each clause consists of a column name followed by 'asc' (ascending, which is the default) or 'desc' (descending). This list specifies how to order the results in order of precedence.
22702293
top | `number` | Number of suggestions to retrieve. The default is **5**.
22712294
2272-
**SuggestionOptions**
2295+
**SuggestOptions**
2296+
22732297
Options are settings configured to search a search term.
22742298
22752299
Property Name | Type | Description
22762300
------------ | ------------- | -------------
2277-
advancedSuggestEnabled | `boolean` | Enables advanced suggestions for the search query. The default is false.
2301+
advancedSuggestEnabled | `boolean` | Enables advanced suggestions for the search query. The default is false. _Tbh, I
2302+
don't know what this option does, the official documentation does not provide any info, so lmk if you know what it is._
22782303
22792304
**Examples:**
22802305
22812306
```ts
22822307
let result = await dynamicsWebApi.suggest({
22832308
query: {
2284-
search: "mar"
2309+
search: "Con"
22852310
}
22862311
});
22872312

2288-
//the same as:
2289-
result = await dynamicsWebApi.suggest("mar");
2313+
//same as:
2314+
result = await dynamicsWebApi.suggest("Con");
22902315

2291-
const firstText = result.Value[0].Text;
2292-
const firstDocument = result.Value[0].Document;
2293-
const error = result.Error;
2316+
//all data for v2 is returned inside the "response" property
2317+
const { Value: value, Error: error } = result.response;
2318+
2319+
if (!error && value.length) {
2320+
const { Text: text, Document: document } = value[0];
2321+
}
22942322
```
22952323
22962324
```ts
2325+
//more complex example:
2326+
22972327
const result = await dynamicsWebApi.suggest({
22982328
query: {
2299-
search: "mar",
2300-
filter: "account:modifiedon ge 2020-04-27T00:00:00," +
2301-
"activities:regardingobjecttypecode eq 'account', annotation:objecttypecode eq 'account'"
2302-
}
2303-
});
2329+
search: "Con",
2330+
entities: [{
2331+
name: "account",
2332+
selectColumns: ["name"],
2333+
}, {
2334+
name: "contact",
2335+
selectColumns: ["fullname"],
2336+
}],
2337+
filter: "modifiedon ge 2020-04-27T00:00:00Z and statecode eq 0",
2338+
orderBy: ["modifiedon asc"],
2339+
fuzzy: true,
2340+
},
2341+
});
2342+
2343+
const { Value: value, Error: error } = result.response;
2344+
2345+
if (!error && value.length) {
2346+
const { Text: text, Document: document } = value[0];
2347+
}
23042348
```
23052349
23062350
### Autocomplete
23072351
2352+
> [!WARNING]
2353+
> **Checked: May 11th, 2025.**
2354+
> Something is wrong with this Search API endpoint. Does not matter what requests are done, I always get an error:
2355+
>
2356+
> `Invalid expression: Unsupported function call: search.ismatchscoring. This function is only supported in the Search API. Parameter name: $filter.`
2357+
>
2358+
This looks like and ootb issue, they are using an unsupported operator `search.ismatchscoring` in a [Search Service's Autocomplete query](https://learn.microsoft.com/en-us/azure/search/search-query-odata-full-text-search-functions) function. Let me know if this gets resolved, I will remove the warning.
2359+
>
2360+
> P.S. Neither v1, v2 nor `searchautocomplete` action are working.
2361+
23082362
The following table describes all parameters for an `autocomplete` request:
23092363

23102364
Property Name | Type | Description
@@ -2323,21 +2377,34 @@ let result = await dynamicsWebApi.autocomplete({
23232377
}
23242378
});
23252379
2326-
//the same as:
2380+
//it's similar to:
23272381
result = await dynamicsWebApi.autocomplete("mar");
23282382
2329-
const error = result.Error;
2330-
const value = result.Value;
2383+
//all data for v2 is returned inside the "response" property
2384+
const { Value: value, Error: error } = result.response;
23312385
```
23322386

23332387
```ts
2388+
//a more complex request
2389+
23342390
const result = await dynamicsWebApi.autocomplete({
23352391
query: {
2336-
search: "mar",
2337-
filter: "account:modifiedon ge 2020-04-27T00:00:00," +
2338-
"activities:regardingobjecttypecode eq 'account', annotation:objecttypecode eq 'account'"
2339-
}
2392+
search: "tes",
2393+
entities: [{
2394+
name: "account",
2395+
selectColumns: ["name", "createdon"],
2396+
searchColumns: ["name"],
2397+
}],
2398+
filter: "modifiedon ge 2020-04-27T00:00:00Z and statecode eq 0",
2399+
fuzzy: true,
2400+
},
23402401
});
2402+
2403+
const { Value: value, Error: error } = result.response;
2404+
2405+
if (!error) {
2406+
console.log("Autocompleted:", value);
2407+
}
23412408
```
23422409

23432410
## Retrieve CSDL $metadata document
@@ -2350,7 +2417,8 @@ const request: DynamicsWebApi.CsdlMetadataRequest = {
23502417
}
23512418
23522419
//the parameter "request" is optional and can be ommited if additional annotations are not necessary
2353-
const csdlDocument: string = await dynamicsWebApi.retrieveCsdlMetadata(request);
2420+
const csdlDocument: string =
2421+
await dynamicsWebApi.retrieveCsdlMetadata(request);
23542422
```
23552423

23562424
The `csdlDocument` will be the type of `string`. DynamicsWebApi does not parse the contents of the document and it should be done by the developer.
@@ -2406,7 +2474,8 @@ const backgroundOperation = await dynamicsWebApi.retrieve({
24062474
});
24072475
24082476
// 2. getting the status from the status monitor
2409-
const backgroundOperationStatus = await dynamicsWebApi.getBackgroundOperationStatus(backgroundOperationId);
2477+
const backgroundOperationStatus =
2478+
await dynamicsWebApi.getBackgroundOperationStatus(backgroundOperationId);
24102479
```
24112480

24122481
### Cancel background operation
@@ -2425,7 +2494,8 @@ await dynamicsWebApi.update({
24252494
24262495
//or via the status monitor
24272496
2428-
const backgroundOperationStatus = await dynamicsWebApi.cancelBackgroundOperation(backgroundOperationId);
2497+
const backgroundOperationStatus =
2498+
await dynamicsWebApi.cancelBackgroundOperation(backgroundOperationId);
24292499
```
24302500

24312501
### Request a callback

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ As well as Microsoft Dynamics 365 CE (online), Microsoft Dynamics 365 CE (on-pre
1212

1313
## Main Features
1414

15-
- **Microsoft Dataverse Search API**. Access the full power of its Search, Suggestion and Autocomplete capabilities.
15+
- **Microsoft Dataverse Search API**. Access the full power of its Search (Query), Suggestion and Autocomplete capabilities.
1616
- **Batch Requests**. Convert all requests into a Batch operation with two lines of code.
1717
- **Simplicity and Automation**. Automated paging, big file downloading/uploading in chunks of data, automated conversion of requests with long URLs into a Batch Request and more!
1818
- **CRUD operations**. Including Fetch XML, Actions and Functions in Microsoft Dataverse Web API.

tests/searchApi.convertQuery.spec.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ describe("convertSearchQuery", () => {
572572
search: "test",
573573
orderBy: JSON.stringify(["name desc", "contactname asc"]),
574574
};
575-
convertQuery(suggestQuery, "1.0");
575+
convertSuggestOrAutocompleteQuery(suggestQuery, "1.0");
576576

577577
expect(suggestQuery).to.deep.equal({
578578
search: "test",
@@ -587,23 +587,10 @@ describe("convertSearchQuery", () => {
587587
};
588588

589589
expect(function () {
590-
convertQuery(suggestQuery, "1.0");
590+
convertSuggestOrAutocompleteQuery(suggestQuery, "1.0");
591591
}).to.throw("The 'query.orderBy' property must be a valid JSON string.");
592592
});
593-
594-
it("(string) left as is", () => {
595-
const suggestQuery: Suggest = {
596-
search: "test",
597-
orderBy: "doesnot matter what is in here",
598-
};
599-
600-
convertQuery(suggestQuery, "2.0");
601-
602-
expect(suggestQuery).to.deep.equal({
603-
search: "test",
604-
orderBy: "doesnot matter what is in here",
605-
});
606-
});
593+
607594
});
608595
});
609596
});

0 commit comments

Comments
 (0)