3

因此,我已经成功创建了“包”对象的索引,并且直接的文本查询运行良好。

我很想知道是否/如何使用部分填充的对象(“包”类型)作为搜索条件?

包看起来像:

var packages =  new List<Package> {
            new Package {
                Name = "Maverick",
                TargetBusiness = new Business {
                    Industry = "Retail",
                    BusinessType = BusinessType.Product,
                    LocationType = LocationType.Store
                },
                Description = "Standard package for retail shops"
            },
            new Package {
                Name = "Goose",
                TargetBusiness = new Business {
                    Industry = "Retail",
                    BusinessType = BusinessType.Product,
                    LocationType = LocationType.Online
                },
                Description = "Standard package for ecommerce shops"
            },
            new Package {
                Name = "Viper",
                TargetBusiness = new Business {
                    Industry = "Advertising",
                    BusinessType = BusinessType.Service,
                    LocationType = LocationType.Office
                },
                Description = "Standard package test retail"
            }
        }

查询当前看起来像:

var result = client.Search<Package>(x => x.Query(q => q.QueryString(qs => qs.Query("q=retail"))));

但我喜欢有类似的东西:

var result = client.Search<Package>(x => x.Query(q => q.Object(new Package{...etc ...})));

我希望我说得通:D提前谢谢

4

2 回答 2

2
var result = client.Search<Package>(x => x.Query(q => q.Object(new Package{...etc ...})));

永远无法工作,因为Nest无法推断要对对象上的每个属性使用什么类型的查询(即术语、前缀、通配符、query_string 等)。

在您的示例中q=retail仅有效,因为elasticsearch会将查询分解为q OR retail. 您可以使用常规 lucene 语法来定位字段,即targetBusiness.industry:retail.

在弹性搜索中,如果您的查询字符串未绑定到某个字段,则默认情况下会在该字段中搜索,该_all字段将包含对象所有属性的所有术语。这就是为什么如果你真的有很多数据,关闭_all支持通常是一个非常好的主意。

Nest目前没有这样的功能,它可以获取部分填充的对象并将其转换为弹性query_string搜索查询。

说如果这是您的查询:

client.Search<Package>(s=>s
    .From(0)
    .Size(10)
    .Filter(f=>
        f.Term(p=>p.TargetBusiness.Industry, "Advertising")
        && f.Exists(p=>p.Name)
    )
    .Query(q=>
       q.QueryString(qs=>qs
           .Query("ecommerce")
           .Operator(Operator.and)
       )
    )
)

在上面的示例中,您必须创建自己的方法,根据您的包在查询字符串查询中提供要搜索的所有术语。

IE

public string MyPackageQueryString(Package package) 
{
    var myTerms = List<string>();
    myTerms.Add(package.Name);
    if (package.TargetBusiness != null)
    {
        myTerms.Add(package.Industry)
        ....
    }
    ...
    return string.Join(" ", myTerms.Where(t=>!string.IsNullOrWhiteSpace(t)));
}

进而

client.Search<Package>(s=>s
    .From(0)
    .Size(10)
    .Filter(f=>
        f.Term(p=>p.TargetBusiness.Industry, "Advertising")
        && f.Exists(p=>p.Name)
    )
    .Query(q=>
       q.QueryString(qs=>qs
           .Query(this.MyPackageQueryString(package))
           .Operator(Operator.or)
       )
    )
)
于 2012-11-11T14:27:21.847 回答
0

这确实帮助我走上了正确的轨道——最终看起来像是一种交叉搜索:用我不想要的所有其他字段搜索每个字段。

最终(可能不正确)与:

return _searchClient.Search<Package>(s => s.Query(q => 
        q.Term("industry", criteriaPackage.TargetBusiness.Industry.ToLower()) ||
        q.Term("description", criteriaPackage.TargetBusiness.Description.ToLower()) ||
        q.Term("businessType",((int)criteriaPackage.TargetBusiness.BusinessType).ToString()) ||
        q.Term("locationType", ((int)criteriaPackage.TargetBusiness.LocationType).ToString()) ||
        q.Term("marketSegment", criteriaPackage.TargetBusiness.MarketSegment.ToLower()) ||
        q.Term("offer", criteriaPackage.TargetBusiness.Offer.ToLower()))
      ).Documents;

经过几次单元测试后似乎产生了我想要的结果。

于 2012-11-12T15:19:32.400 回答