通过


Dataverse 搜索查询

查询操作基于搜索词返回搜索结果。

除了搜索词,还可以通过传递以下参数的值来影响结果:

名称 类型 说明 详细信息
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 以及 wifiluxury(或两者)的结果。
通配符 支持尾随通配符。 例如,Alp* 搜索“alpine”。
完全匹配 用引号 " "括起来的查询。

注释

若要在搜索文本中使用任何搜索运算符,请在字符前添加单个反斜杠 (\) 进行转义。 需要转义的特殊字符包括以下内容:+ - & | ! ( ) { } [ ] ^ " ~ * ? : \ /

例如,转义后的电话号码可能如下所示:\+1\(800\)555\-1234

通过使用参数options,可以启用Lucerne 查询语法,从而支持不同运算符。

count 参数

类型:bool
可选:true

是否返回总记录数。 如果未设置此参数,则 Count 响应属性为 -1.

entities 参数

类型:string
可选:true

默认情况下,搜索包括启用搜索的所有表。 若要搜索特定子集,请使用 entities 参数。

设置实体时,还可以指定要返回的列和要搜索的列。 还可以为表格包含筛选条件。

若要获取为环境启用的表列表,请使用 搜索状态 API 并查找在 entitylogicalnameentitystatusresults列出的表。

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-countvalue-value。 使用countcount降序排序。 使用 -count 按升序对 count 进行排序。 使用 valuevalue 进行升序排序。 使用 -valuevalue 进行降序排序。
values 设置为以竖线分隔的数字或 Edm.DateTimeOffset 值,以指定一组动态的筛选条目值。 这些值必须按顺序按升序列出才能获取预期结果。
interval 数字或分钟、小时、日、周、月、季度、年等日期时间值的整数间隔大于零。
timeoffset 设置为 ([+-]hh:mm[+-]hhmm[+-]hh) 。 如果使用,请将timeoffset参数与间隔选项结合使用,并且仅在应用于Edm.DateTimeOffset类型的字段时。 该值指定在设置时间边界时要考虑的 UTC 时间偏移量。

注释

您可以在同一属性规范中合并countsort,但不能将它们与intervalvalues合并。 你也不能将 intervalvalues 组合在一起。

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

筛选器限制搜索结果的范围。 使用筛选器排除不需要的结果。 此顶级筛选器有助于跨多个实体(例如 createdonmodifiedon)筛选常见列。

使用以下语法应用筛选器: <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 值可以是 simpleluceneLucerne 查询语法
besteffortsearchenabled 启用智能查询工作流,以便在未找到与搜索请求术语完全匹配的结果时,返回一组可能的结果。
groupranking 在优化后的响应中启用结果排名,以便在搜索结果页面中按表格分组显示结果。
searchmode 当指定为all时,必须匹配搜索词才能将文档视为符合项。 将其值设置为 any 默认值以匹配搜索词中的任何单词。

Lucene 查询语法

Lucene 查询语法支持以下功能:

功能性 说明
布尔运算符 提供比简单查询语法更全面的扩展集。
AND 运算符,表示为AND&&+
OR 运算符; 表示为 OR||
NOT 运算符; 由 NOT! 表示
通配符 除了尾随通配符外,还支持前导通配符。
尾随通配符 – alp*
前导通配符 - /.*pine/
模糊搜索 支持拼错最多两个字符的查询。
Uniersty~ 返回 University
Blue~1 返回 glueblues
术语提升 以不同的方式权衡查询中的特定术语。
Rock^2 electronic 返回结果,其中匹配 rock 项比匹配 electronic项更重要。
邻近搜索 返回的结果中搜索词彼此在 x 个词以内,以获得更多上下文结果。
例如,"airport hotel"~5返回结果,其中airporthotel在五个单词之内,从而增加找到靠近机场的酒店的机会。
正则表达式搜索 例如, /[mh]otel/ 匹配 motelhotel

orderby 参数

类型:string
可选:true

使用 orderby 参数替代默认排序。 默认情况下,结果按相关性分数的降序列出(@search.score)。 对于分数相同的结果,排序是随机的。 只有当查询类型为 lucene 并且查询字符串中包含通配符时,才能使用此参数。

使用逗号分隔子句的列表,其中每个子句由后跟 asc 列名(升序,即默认值)或 desc (降序)组成。

对于包含多个表类型的一组结果,子句列表 orderby 必须可在全局范围内适用(例如,modifiedoncreatedon@search.score)。 例如,要按相关性(优先级顺序)排序结果,并让最近修改的记录排在更靠前的位置:

"orderby": ["@search.score desc", "modifiedon desc"]

如果查询请求包含特定表类型的筛选器, orderby 可以选择指定特定于表的列。

skiptop 参数

类型: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 日之后创建的记录,这些示例分别对帐户和联系人表 namefullname 列执行搜索操作,并按 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 旧版搜索