查询操作基于搜索词返回搜索结果。
除了搜索词,还可以通过传递以下参数的值来影响结果:
| 名称 | 类型 | 说明 | 详细信息 |
|---|---|---|---|
search |
字符串 | 必需。 要搜索的文本。 | 搜索参数 |
count |
布尔 | 是否返回总记录计数。 |
count 参数 |
entities |
字符串 | 将搜索范围限制为表的子集。 | entities 参数 |
facets |
字符串 | Facet 支持在检索数据结果后,向下钻取数据结果。 | facets 参数 |
filter |
字符串 | 限制返回的搜索结果的范围。 | filter 参数 |
options |
字符串 | 选项是用于配置以便于搜索某个搜索词的设置。 |
options 参数 |
orderby |
字符串 | 指定如何按优先顺序对结果进行排序。 | orderby 参数 |
skip |
int | 指定要跳过的搜索结果数。 | skip 和 top 参数 |
top |
int | 指定要检索的搜索结果数。 | skip 和 top 参数 |
参数
本部分包括有关上表中引入的参数的详细信息。
search 参数
类型:string
必需:true
搜索参数包含要搜索的文本。 它是唯一必需的参数。 搜索词长度必须至少为一个字符,并且具有 100 个字符的限制。
简单搜索语法
默认情况下,搜索参数支持简单的搜索语法,如下表所述:
| 功能性 | 说明 |
|---|---|
| 布尔运算符 | AND 运算符,用+表示OR 运算符;用 | 表示NOT 运算符;表示为 - |
| 优先运算符 | 搜索词 hotel+(wifi | luxury) 用于查找包含字词 hotel 以及 wifi 或 luxury(或两者)的结果。 |
| 通配符 | 支持尾随通配符。 例如,Alp* 搜索“alpine”。 |
| 完全匹配 | 用引号 " "括起来的查询。 |
注释
若要在搜索文本中使用任何搜索运算符,请在字符前添加单个反斜杠 (\) 进行转义。 需要转义的特殊字符包括以下内容:+ - & | ! ( ) { } [ ] ^ " ~ * ? : \ /。
例如,转义后的电话号码可能如下所示:\+1\(800\)555\-1234。
通过使用参数options,可以启用Lucerne 查询语法,从而支持不同运算符。
count 参数
类型:bool
可选:true
是否返回总记录数。 如果未设置此参数,则 Count 响应属性为 -1.
entities 参数
类型:string
可选:true
默认情况下,搜索包括启用搜索的所有表。 若要搜索特定子集,请使用 entities 参数。
设置实体时,还可以指定要返回的列和要搜索的列。 还可以为表格包含筛选条件。
若要获取为环境启用的表列表,请使用 搜索状态 API 并查找在 entitylogicalname 内 entitystatusresults列出的表。
SearchEntity 类型
使用此类型可组合要传递给 entities 参数的表数组。
| 字段名称 | 类型 | 说明 |
|---|---|---|
name |
字符串 | 必填。 表的逻辑名称。 指定查询的范围。 |
selectColumns |
字符串[] | 可选。 响应中返回表文档时要投影的列列表。 如果为空,则仅返回表主名称。 |
searchColumns |
字符串[] | 可选。 用于限定查询范围的列列表。 若为空,则仅搜索表的主名称。 |
filter |
字符串 | 可选。 应用于实体的过滤器。 |
示例
以下示例显示了使用上述架构的一些 JSON 数据。
[
{
"name":"account",
"selectColumns":["name","address1_city"],
"searchColumns":["name","address1_city"],
"filter":"modifiedon ge 2018-01-01T00:00:00Z"
},
{
"name":"contact",
"selectColumns":["fullname","address1_city"],
"searchColumns":["fullname","address1_city"],
"filter":"modifiedon ge 2018-01-01T00:00:00Z"
}
]
要使用此数据,请对字符串进行转义,并将其作为 entities 参数的值传递到请求主体中:
{
"search": "maria",
"entities":"[{\"name\":\"account\",\"selectColumns\":[\"name\",\"address1_city\"],\"searchColumns\":[\"name\",\"address1_city\"],\"filter\":\"modifiedon ge 2018-01-01T00:00:00Z\"},{\"name\":\"contact\",\"selectColumns\":[\"fullname\",\"address1_city\"],\"searchColumns\":[\"fullname\",\"address1_city\"],\"filter\":\"modifiedon ge 2018-01-01T00:00:00Z\"}]"
}
facets 参数
类型:string
可选:true
facet 参数是可选的。 字符串可能包含用于自定义分面的参数,以逗号分隔的名称/值对表示。 使用维度对搜索结果进行分组。
面定义
将 facet 定义为字符串数组,例如:
[
"entityname,count:100",
"account:primarycontactid,count:100",
"ownerid,count:100",
"modifiedon,values:2019-04-27T00:00:00|2020-03-27T00:00:00|2020-04-20T00:00:00|2020-04-27T00:00:00",
"createdon,values:2019-04-27T00:00:00|2020-03-27T00:00:00|2020-04-20T00:00:00|2020-04-27T00:00:00"
]
数组中的每个项都表示对查询返回的数据进行分组的不同方法。 对于返回的每个属性,请使用下表中的值指定适当的分面:
| Facet 类型 | 说明 |
|---|---|
count |
分面术语的最大数量。 默认值是10。 没有上限。 |
sort |
设置为count、-count或 value-value。 使用count按count降序排序。 使用 -count 按升序对 count 进行排序。 使用 value 按 value 进行升序排序。 使用 -value 对 value 进行降序排序。 |
values |
设置为以竖线分隔的数字或 Edm.DateTimeOffset 值,以指定一组动态的筛选条目值。 这些值必须按顺序按升序列出才能获取预期结果。 |
interval |
数字或分钟、小时、日、周、月、季度、年等日期时间值的整数间隔大于零。 |
timeoffset |
设置为 ([+-]hh:mm, [+-]hhmm或 [+-]hh) 。 如果使用,请将timeoffset参数与间隔选项结合使用,并且仅在应用于Edm.DateTimeOffset类型的字段时。 该值指定在设置时间边界时要考虑的 UTC 时间偏移量。 |
注释
您可以在同一属性规范中合并count和sort,但不能将它们与interval或values合并。 你也不能将 interval 和 values 组合在一起。
将 facets 值设置为包含筛选器定义的转义字符串。
{
"search": "maria",
"facets": "[\"entityname,count:100\",\"account:primarycontactid,count:100\",\"ownerid,count:100\",\"modifiedon,values:2019-04-27T00:00:00|2020-03-27T00:00:00|2020-04-20T00:00:00|2020-04-27T00:00:00\",\"createdon,values:2019-04-27T00:00:00|2020-03-27T00:00:00|2020-04-20T00:00:00|2020-04-27T00:00:00\"]"
}
有关详细信息,请参见:
filter 参数
类型:string
可选:true
筛选器限制搜索结果的范围。 使用筛选器排除不需要的结果。 此顶级筛选器有助于跨多个实体(例如 createdon 或 modifiedon)筛选常见列。
使用以下语法应用筛选器: <attribute logical name> <filter> 表逻辑名称指定筛选器适用的实体。
筛选器使用以下查询运算符:
| Operator | 说明 | 示例 |
|---|---|---|
| 比较运算符 | ||
eq |
Equal | revenue eq 100000 |
ne |
不等于 | revenue ne 100000 |
gt |
大于 | revenue gt 100000 |
ge |
大于或等于 | revenue ge 100000 |
lt |
小于 | revenue lt 100000 |
le |
小于或等于 | revenue le 100000 |
| 逻辑运算符 | ||
and |
逻辑与 | revenue lt 100000 and revenue gt 2000 |
or |
逻辑或 | name eq 'sample' or name eq 'test' |
not |
逻辑非 | not name eq 'sample' |
| 分组运算符 | ||
( ) |
优先分组 | (name eq 'sample') or name eq 'test') and revenue gt 5000 |
options 参数
类型:string
可选:true
选项是用于配置搜索词的设置。 将 options 值设置为这些选项的序列化 Dictionary<string, string> 形式,例如 "{'querytype': 'lucene', 'searchmode': 'all', 'besteffortsearchenabled': 'true', 'grouprankingenabled': 'true'}"。
下表列出了这些选项:
| 选项 | 说明 |
|---|---|
querytype |
值可以是 simple 或 luceneLucerne 查询语法 |
besteffortsearchenabled |
启用智能查询工作流,以便在未找到与搜索请求术语完全匹配的结果时,返回一组可能的结果。 |
groupranking |
在优化后的响应中启用结果排名,以便在搜索结果页面中按表格分组显示结果。 |
searchmode |
当指定为all时,必须匹配搜索词才能将文档视为符合项。 将其值设置为 any 默认值以匹配搜索词中的任何单词。 |
Lucene 查询语法
Lucene 查询语法支持以下功能:
| 功能性 | 说明 |
|---|---|
| 布尔运算符 | 提供比简单查询语法更全面的扩展集。 AND 运算符,表示为 AND、&&、+OR 运算符; 表示为 OR, ||NOT 运算符; 由 NOT、!、– 表示 |
| 通配符 | 除了尾随通配符外,还支持前导通配符。 尾随通配符 – alp*前导通配符 - /.*pine/ |
| 模糊搜索 | 支持拼错最多两个字符的查询。Uniersty~ 返回 UniversityBlue~1 返回 glue, blues |
| 术语提升 | 以不同的方式权衡查询中的特定术语。Rock^2 electronic 返回结果,其中匹配 rock 项比匹配 electronic项更重要。 |
| 邻近搜索 | 返回的结果中搜索词彼此在 x 个词以内,以获得更多上下文结果。 例如, "airport hotel"~5返回结果,其中airport和hotel在五个单词之内,从而增加找到靠近机场的酒店的机会。 |
| 正则表达式搜索 | 例如, /[mh]otel/ 匹配 motel 或 hotel。 |
orderby 参数
类型:string
可选:true
使用 orderby 参数替代默认排序。 默认情况下,结果按相关性分数的降序列出(@search.score)。 对于分数相同的结果,排序是随机的。 只有当查询类型为 lucene 并且查询字符串中包含通配符时,才能使用此参数。
使用逗号分隔子句的列表,其中每个子句由后跟 asc 列名(升序,即默认值)或 desc (降序)组成。
对于包含多个表类型的一组结果,子句列表 orderby 必须可在全局范围内适用(例如,modifiedon,createdon,@search.score)。 例如,要按相关性(优先级顺序)排序结果,并让最近修改的记录排在更靠前的位置:
"orderby": ["@search.score desc", "modifiedon desc"]
如果查询请求包含特定表类型的筛选器, orderby 可以选择指定特定于表的列。
skip 和 top 参数
类型:int
可选:true
将这些参数与 count 参数 一起使用来创建分页体验。
默认情况下,每次返回最多 50 个结果。 使用 top 可以将其提高到 100,但更常用的是 top 来指定较小的结果集(例如 10),然后在用户移动到下一页时使用 skip 来跳过之前返回的结果。
响应
查询操作的响应是包含 JSON 数据的转义字符串。
未转义的响应包含使用以下属性的 JSON。
| 名称 | 类型 | 说明 |
|---|---|---|
Error |
ErrorDetail | 提供 Azure 认知搜索中的错误信息。 |
Value |
QueryResult[] |
匹配记录的集合。 |
Facets |
Dictionary<string,
FacetResult[]> |
如果查询请求分面,则提供一个包含分面值的字典。 |
QueryContext |
QueryContext | 此属性用于后端搜索。 它包含在将来的功能版本中,当前未使用。 |
Count |
long | 如果请求正文包含 "Count": true,则计算所有与搜索匹配的文档数量,此时忽略 top 和 skip 参数。 |
响应类型
本部分介绍响应返回的类型。
错误详细信息
作为响应一部分返回的 Azure Cognitive Search 错误。
| 名称 | 类型 | 说明 |
|---|---|---|
code |
字符串 | 错误代码。 |
message |
字符串 | 错误消息。 |
propertybag |
Dictionary<string, object> |
更多错误信息。 |
查询结果
响应QueryResult属性中返回的每个Value项都表示 Dataverse 中的记录。
| 名称 | 类型 | 说明 |
|---|---|---|
Id |
字符串 | 记录的标识符。 |
EntityName |
字符串 | 表的逻辑名称。 |
ObjectTypeCode |
int | 对象类型代码。 |
Attributes |
Dictionary<string, object> |
记录属性 |
Highlights |
Dictionary<string, string[]> |
亮点。 |
Score |
双精度 | 文档分数。 |
FacetResult
一个分面查询结果,报告具有特定范围、特定值或特定区间的字段的文档数量。
| 名称 | 类型 | 说明 |
|---|---|---|
count |
长型? | 属于此分面所描述的桶内的文档数量。 |
from |
对象 | 表示分面范围包含下限的值,或为 null 表示无下限。 |
to |
对象 | 表示分面范围不包含上界的值,或为 null 表示无上限。 |
type |
Value | Range |
分面的类型。 |
value |
对象 | 分面的值,如果是区间分面,则为包含下限。 |
optionalvalue |
对象 | 分面的另一个或可选值,在对查找进行分面时填充。 |
QueryContext
作为响应的一部分返回的查询上下文。 此属性用于后端搜索。 它包含在将来的功能版本中,当前未使用。
| 名称 | 类型 | 说明 |
|---|---|---|
originalquery |
字符串 | 请求中指定的查询字符串。 |
alteredquery |
字符串 | Dataverse 搜索用于执行查询的查询字符串。 如果原始查询字符串包含拼写错误或未产生最佳结果,Dataverse 搜索将使用更改的查询字符串。 |
reason |
字符串[] | Dataverse 搜索查询更改决策背后的原因。 |
spellsuggestions |
字符串[] | 拼写建议,即可能代表用户意图的词汇。 仅当 Dataverse 因拼写检查而更改查询时才会填充。 |
示例
以下示例演示如何使用查询操作。 对于在 2022 年 8 月 15 日之后创建的记录,这些示例分别对帐户和联系人表 name 和 fullname 列执行搜索操作,并按 createdon 字段降序对前七个结果进行排序。
此示例来自 GitHub 上的 SDK for .NET 搜索操作示例 。 静态 OutputSearchQuery 方法接受 搜索参数的值。
/// <summary>
/// Demonstrate query API
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="searchTerm">The term to search for</param>
/// <returns></returns>
static void OutputSearchQuery(IOrganizationService service, string searchTerm)
{
Console.WriteLine("OutputSearchQuery START\n");
searchqueryRequest request = new() {
search = searchTerm,
count = true,
top = 7,
entities = JsonConvert.SerializeObject(new List<SearchEntity>()
{
new SearchEntity()
{
Name = "account",
SelectColumns = new List<string>() { "name", "createdon" },
SearchColumns = new List<string>() { "name" },
Filter = "statecode eq 0"
},
new SearchEntity()
{
Name = "contact",
SelectColumns = new List<string>() { "fullname", "createdon" },
SearchColumns = new List<string>() { "fullname" },
Filter = "statecode eq 0"
}
}),
orderby = JsonConvert.SerializeObject(new List<string>() { "createdon desc" }),
filter = "createdon gt 2022-08-15"
};
var searchqueryResponse = (searchqueryResponse)service.Execute(request);
var queryResults = JsonConvert.DeserializeObject<SearchQueryResults>(searchqueryResponse.response);
Console.WriteLine($"\tCount:{queryResults.Count}");
Console.WriteLine("\tValue:");
queryResults.Value.ForEach(result =>
{
Console.WriteLine($"\t\tId:{result.Id}");
Console.WriteLine($"\t\tEntityName:{result.EntityName}");
Console.WriteLine($"\t\tObjectTypeCode:{result.ObjectTypeCode}");
Console.WriteLine("\t\tAttributes:");
foreach (string key in result.Attributes.Keys)
{
Console.WriteLine($"\t\t\t{key}:{result.Attributes[key]}");
}
Console.WriteLine("\t\tHighlights:");
foreach (string key in result.Highlights.Keys)
{
Console.WriteLine($"\t\t\t{key}:");
foreach (string value in result.Highlights[key])
{
Console.WriteLine($"\t\t\t\t{value}:");
}
}
Console.WriteLine($"\t\tScore:{result.Score}\n");
});
Console.WriteLine("OutputSearchQuery END\n");
}
输出
使用经过身份验证的ServiceClient类实例调用OutputSearchQuery方法,并在调用过程中将searchTerm设为“Contoso”时:
OutputSearchQuery(service: serviceClient, searchTerm: "Contoso");
输出与下面类似:
OutputSearchQuery START
Count:1
Value:
Id:8b35eda1-ef69-ee11-9ae7-000d3a88a4a2
EntityName:account
ObjectTypeCode:0
Attributes:
@search.objecttypecode:1
name:Contoso Pharmaceuticals (sample)
createdon:10/13/2023 5:41:21 PM
createdon@OData.Community.Display.V1.FormattedValue:10/13/2023 5:41 PM
Highlights:
name:
{crmhit}Contoso{/crmhit} Pharmaceuticals (sample):
Score:4.986711
OutputSearchQuery END
辅助类
该方法 OutputSearchQuery 取决于以下支持类来发送请求并处理结果:
searchqueryRequest 和 searchqueryResponse 类
使用 Power Platform CLI 下的 pac modelbuilder build 命令生成这些类,如 生成适用于 .NET 的 SDK 早期绑定类中所述。
SearchEntity 类
使用此类撰写 SearchEntity 类型 数据。
public sealed class SearchEntity
{
/// <summary>
/// Gets or sets the logical name of the table. Specifies scope of the query.
/// </summary>
[DataMember(Name = "name", IsRequired = true)]
public string Name { get; set; }
/// <summary>
/// Gets or sets the list of columns that needs to be projected when table documents are returned in response.
/// If empty, only PrimaryName will be returned.
/// </summary>
[DataMember(Name = "selectcolumns")]
public List<string> SelectColumns { get; set; }
/// <summary>
/// Gets or sets the list of columns to scope the query on.
/// If empty, only PrimaryName will be searched on.
/// </summary>
[DataMember(Name = "searchcolumns")]
public List<string> SearchColumns { get; set; }
/// <summary>
/// Gets or sets the filters applied on the entity.
/// </summary>
[DataMember(Name = "filter")]
public string Filter { get; set; }
}
SearchQueryResults 类
使用此类从 searchqueryResponse.response 字符串属性反序列化 JSON 数据。
public sealed class SearchQueryResults
{
/// <summary>
/// Provides error information from Azure Cognitive search.
/// </summary>
public ErrorDetail? Error { get; set; }
/// <summary>
/// A collection of matching records.
/// </summary>
public List<QueryResult>? Value { get; set; }
/// <summary>
/// If facets were requested in the query, a dictionary of facet values.
/// </summary>
public Dictionary<string, IList<FacetResult>>? Facets { get; set; }
/// <summary>
/// The query context returned as part of response. This property is used for backend search. It is included for future feature releases and is not currently used.
/// </summary>
public QueryContext? QueryContext { get; set; }
/// <summary>
/// If `"Count": true` is included in the body of the request, the count of all documents that match the search, ignoring top and skip.
/// </summary>
public long Count { get; set; }
}
ErrorDetail 类
使用此类反序列化 ErrorDetail 数据。
public sealed class ErrorDetail
{
/// <summary>
/// Gets or sets the error code.
/// </summary>
[DataMember(Name = "code")]
public string Code { get; set; }
/// <summary>
/// Gets or sets the error message.
/// </summary>
[DataMember(Name = "message")]
public string Message { get; set; }
/// <summary>
/// Gets or sets additional error information.
/// </summary>
[DataMember(Name = "propertybag")]
public Dictionary<string, object> PropertyBag { get; set; }
}
QueryResult 类
使用此类反序列化 QueryResult 数据。
public sealed class QueryResult
{
/// <summary>
/// Gets or sets the identifier of the record
/// </summary>
public string Id { get; set; }
/// <summary>
/// Gets or sets the logical name of the table
/// </summary>
public string EntityName { get; set; }
/// <summary>
/// Gets or sets the object type code
/// </summary>
public int ObjectTypeCode { get; set; }
/// <summary>
/// Gets or sets the record attributes
/// </summary>
public Dictionary<string, object> Attributes { get; set; }
/// <summary>
/// Gets or sets the highlights
/// </summary>
public Dictionary<string, string[]> Highlights { get; set; }
// Gets or sets the document score
public double Score { get; set; }
}
FacetResult 类
使用此类反序列化 FacetResult 数据。
public sealed class FacetResult
{
/// <summary>
/// Gets or sets the count of documents falling within the bucket described by this facet.
/// </summary>
[DataMember(Name = "count")]
public long? Count { get; set; }
/// <summary>
/// Gets or sets value indicating the inclusive lower bound of the facet's range, or null to indicate that there is no lower bound.
/// </summary>
[DataMember(Name = "from")]
public object From { get; set; }
/// <summary>
/// Gets or sets value indicating the exclusive upper bound of the facet's range, or null to indicate that there is no upper bound.
/// </summary>
[DataMember(Name = "to")]
public object To { get; set; }
/// <summary>
/// Gets or sets type of the facet - Value or Range.
/// </summary>
[DataMember(Name = "type")]
public FacetType Type { get; set; }
/// <summary>
/// Gets or sets value of the facet, or the inclusive lower bound if it's an interval facet.
/// </summary>
[DataMember(Name = "value")]
public object Value { get; set; }
/// <summary>
/// Gets or sets additional/ Optional value of the facet, will be populated while faceting on lookups.
/// </summary>
[DataMember(Name = "optionalvalue")]
public object OptionalValue { get; set; }
}
FacetType 类
指定分面查询结果的类型。
public enum FacetType
{
/// <summary>
/// The facet counts documents with a particular field value.
/// </summary>
[EnumMember(Value = "value")]
Value = 0,
/// <summary>
/// The facet counts documents with a field value in a particular range.
/// </summary>
[EnumMember(Value = "range")]
Range = 1,
}
QueryContext 类
使用此类反序列化 QueryContext 数据。
public sealed class QueryContext
{
/// <summary>
/// Gets or sets the query string as specified in the request.
/// </summary>
[DataMember(Name = "originalquery")]
public string OriginalQuery { get; set; }
/// <summary>
/// Gets or sets the query string that Dataverse search used to perform the query.
/// Dataverse search uses the altered query string if the original query string contained spelling mistakes or did not yield optimal results.
/// </summary>
[DataMember(Name = "alteredquery")]
public string AlteredQuery { get; set; }
/// <summary>
/// Gets or sets the reason behind query alter decision by Dataverse search.
/// </summary>
[DataMember(Name = "reason")]
public List<string> Reason { get; set; }
/// <summary>
/// Gets or sets the spell suggestion that are the likely words that represent user's intent.
/// This will be populated only when the query was altered by Dataverse search due to spell check.
/// </summary>
[DataMember(Name = "spellsuggestions")]
public List<string> SpellSuggestions { get; set; }
}
另见
搜索Dataverse记录
Dataverse 搜索建议
Dataverse 搜索自动完成
Dataverse 搜索统计信息和状态
Dataverse 旧版搜索