You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Examine搜索Microsoft Graph用户时的短语搜索异常问题

解决Examine多字段精确短语搜索问题

问题概述

使用Examine搜索Microsoft Graph用户列表时,执行短语搜索"Project Controller",返回结果包含所有含Project或Controller的记录,但实际需求是仅返回任意指定字段中包含完整短语的结果。目前实际只有14个用户的JobTitle为Project Controllers,但搜索返回了68条无关结果。

现有代码与生成查询分析

原始查询代码

public async Task<List<User>> Search(string query = "")
{
    string[] terms = query.Split(' ');

    _allUsers = await GetAllUsers();

    List<User> matchingUsers = new List<User>();

    if (_examineManager.TryGetIndex("ColleaguesIndex", out _colleaguesIndex))
    {
        var searchFields = new[] { "FirstName", "LastName", "DisplayName", "StreetAddress", "JobTitle", "Department", "BusinessUnit", "OfficeLocation", "City", "State", "PostalCode", "BusinessPhones", "MobilePhone", "CompanyName" };
        var results = _colleaguesIndex.Searcher.CreateQuery(defaultOperation: BooleanOperation.Or)
                    .GroupedOr(searchFields, query.MultipleCharacterWildcard()).Or()
                    .GroupedOr(searchFields, query.Escape()).Or()                   
                    .GroupedOr(searchFields, terms)
                    .Execute();

        var resultsID = results.Select(r => r.Id);

        matchingUsers = _allUsers.Where(u => resultsID.Contains(u.OnPremisesSamAccountName)).ToList();
    }

    return matchingUsers;
}

生成的查询语句

{
    (
        FirstName     : project controller*
        LastName      : project controller*
        DisplayName   : project controller*
        StreetAddress : project controller*
        JobTitle      : project controller*
        Department    : project controller*
        BusinessUnit  : project controller*
        OfficeLocation: project controller*
        City          : project controller*
        State         : project controller*
        PostalCode    : project controller*
        BusinessPhones: project controller*
        MobilePhone   : project controller*
        CompanyName   : project controller*
    )
    (
        FirstName     : "Project controller"
        LastName      : "Project controller"
        DisplayName   : "Project controller"
        StreetAddress : "Project controller"
        JobTitle      : "Project controller"
        Department    : "Project controller"
        BusinessUnit  : "Project controller"
        OfficeLocation: "Project controller"
        City          : "Project controller"
        State         : "Project controller"
        PostalCode    : "Project controller"
        BusinessPhones: "Project controller"
        MobilePhone   : "Project controller"
        CompanyName   : "Project controller"
    )
    (
        FirstName     : project
        FirstName     : controller
        LastName      : project
        LastName      : controller
        DisplayName   : project
        DisplayName   : controller
        StreetAddress : project
        StreetAddress : controller
        JobTitle      : project
        JobTitle      : controller
        Department    : project
        Department    : controller
        BusinessUnit  : project
        BusinessUnit  : controller
        OfficeLocation: project
        OfficeLocation: controller
        City          : project
        City          : controller
        State         : project
        State         : controller
        PostalCode    : project
        PostalCode    : controller
        BusinessPhones: project
        BusinessPhones: controller
        MobilePhone   : project
        MobilePhone   : controller
        CompanyName   : project
        CompanyName   : controller
    )
}

简化查询测试问题

将查询简化为仅保留精确短语搜索后:

var results = _colleaguesIndex.Searcher.CreateQuery().GroupedOr(searchFields, query.Escape()).Execute();

生成的Lucene查询为:

LuceneQuery: {+(FirstName:"Project Controller" LastName:"Project Controller" DisplayName:"Project Controller" StreetAddress:"Project Controller" JobTitle:"Project Controller" Department:"Project Controller" BusinessUnit:"Project Controller" OfficeLocation:"Project Controller" City:"Project Controller" State:"Project Controller" PostalCode:"Project Controller" BusinessPhones:"Project Controller" MobilePhone:"Project Controller" CompanyName:"Project Controller")}

该查询要求所有字段都匹配短语,因此返回0条结果,不符合需求。

问题根源

  1. 原始查询同时叠加了通配符模糊搜索、精确短语搜索、单词Or搜索,导致结果范围被无限制扩大,包含所有含任意单个关键词的记录。
  2. 简化查询未指定defaultOperation为BooleanOperation.Or,默认采用And逻辑,要求所有字段必须同时匹配短语,显然不符合实际数据分布。
  3. 实际目标数据为复数形式Project Controllers,而搜索词为单数Project Controller,即使逻辑正确也无法匹配到目标记录。

解决方案

核心修改思路

构造仅包含精确短语匹配的查询,指定任意一个搜索字段匹配短语即可命中,同时可选支持复数形式的通配符扩展。

修改后代码

public async Task<List<User>> Search(string query = "")
{
    _allUsers = await GetAllUsers();
    List<User> matchingUsers = new List<User>();

    if (_examineManager.TryGetIndex("ColleaguesIndex", out _colleaguesIndex))
    {
        var searchFields = new[] { "FirstName", "LastName", "DisplayName", "StreetAddress", "JobTitle", "Department", "BusinessUnit", "OfficeLocation", "City", "State", "PostalCode", "BusinessPhones", "MobilePhone", "CompanyName" };
        
        // 构造精确短语查询,若需匹配复数形式(如Project Controllers),使用带通配符的短语
        var searchPhrase = query.Contains(' ') ? $"\"{query}\"" : query;
        // 支持复数:var searchPhrase = query.Contains(' ') ? $"\"{query}*\"" : $"{query}*";

        var results = _colleaguesIndex.Searcher.CreateQuery(defaultOperation: BooleanOperation.Or)
                    .GroupedOr(searchFields, searchPhrase)
                    .Execute();

        var resultsID = results.Select(r => r.Id);
        matchingUsers = _allUsers.Where(u => resultsID.Contains(u.OnPremisesSamAccountName)).ToList();
    }

    return matchingUsers;
}

关键说明

  1. 指定布尔操作逻辑:通过defaultOperation: BooleanOperation.Or确保查询逻辑为「任意字段匹配短语即可」。
  2. 精确短语构造:对含空格的查询用双引号包裹,生成Lucene的精确短语查询语法。
  3. 复数支持:若需匹配Project Controllers这类复数形式,可在短语末尾添加通配符*,构造为"Project Controller*"。

验证结果

修改后执行"Project Controller"搜索(若启用通配符则匹配复数),将仅返回在指定字段中包含完整短语的用户,即预期的14条JobTitle为Project Controllers的记录。

内容的提问来源于stack exchange,提问作者s15199d

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:58:10