Azure搜索返回父记录和子记录

时间:2017-05-06 17:19:46

标签: sql-server azure-search

我们的应用程序管理用户拥有的书籍,书籍包含多个文档(pdf,word docs等)。主页列出了用户的所有书籍,其中包含用于加载接下来10本书籍的分页按钮。然后,当用户点击一本书时,它会在新屏幕中打开并列出该书的所有文档。

到目前为止,我们使用WCF /实体框架来检索主页上显示的所有书籍,然后使用azure搜索(连接到sql视图)来获取一本书打开时的文档,这对于分页很有效和排序。

现在我们还希望从azure搜索中获取用户的所有书籍列表,因此我们创建了一个新表来保存书籍和文档数据,每个文档一行意味着父书名称和书籍ID重复每一行。

AzureSearchTable

我们的天蓝色搜索索引现在指向此表,我必须弄清楚如何为具有分页和可能排序的用户检索书籍。 问题是我需要对书籍进行明确的选择,但是天蓝色的搜索没有区别,我不知道一本书可能有多少文档,所以我不能将Top参数设置为10.一本书可以有30或40个文档,这意味着前40行例如可以只用于一本书。

我试图在书籍ID上使用一个方面,哪种方式有用,并给我每本书的文件的ID和数量,但我似乎无法指定方面的排序顺序 - 顺序不同于我为查询设置的顺序(BookId)。我也不知道如何使用facet获取所有书籍 - 我可以在facet上设置count属性,但我不知道用户将拥有多少本书。

我们的架构师说我应该获得所有行(可能是数千行)并在C#代码中过滤它们以获得10本书。这对我来说似乎效率很低,但感觉不对。

所以我不确定这是不是正确的做法..

  • 我是否应该为书籍和文档数据(使用单独的表?
  • )设置单独的azure搜索索引
  • 如何在不知道每本书有多少文档的情况下从这张表中返回前n本书?
  • 我可以使用C#sdk指定facet的排序顺序吗? (我认为可以通过其余的API)
  • 如何让一个方面为用户返回所有图书?

1 个答案:

答案 0 :(得分:3)

以下是一些想法:

子弹#1回答:

如果您的目的是能够根据对DocumentName的搜索返回书籍列表,那么您可能希望将它们保留在同一索引中。您的架构师在C#中处理结果的想法可能没有您想象的那么糟糕。您可以在LINQ中执行GroupBy。 Azure搜索查询很快,LINQ查询也是如此。特别是如果发出Azure搜索查询的计算机是Azure Web / app服务器并且位于同一区域(数据中​​心内部通信)。我已经使用了这种方法,即使是使用Suggestions API进行自动完成功能,需要在用户输入时快速返回结果(在几百毫秒内)。我想说这至少值得一试,看看你用最大和典型的数据集获得了什么样的性能。

但是,如果这对您不起作用,那么请考虑重新构建索引架构,以便DocumentName的类型为Collection(Edm.String)。你会看起来像这样:

{
    id: 20663,
    userId: 1,
    bookId: 2144,
    bookName: "ber",
    documentName: ["asdasd", "_318-1991.jpg", "wallhaven-13081.png", etc...],
    documentCount: 7
}

现在,如果您需要允许用户获取有关他们选择的特定图书文档的详细信息,您可以通过数据库调用来获取图书详细信息。或者,您可以 为具有更详细文档信息的文档创建另一个Azure搜索索引。但是在用户工作流程的这一点上,除非您要在该特定书籍的文档中提供另一个全文搜索,那么您可能只想坚持使用id-get-id类型的DB调用。 / p>

子弹#2回答:

对于文档计数,您可以创建另一个字段(如上所示)并对其进行排序/过滤/构面。

子弹#3回答:

SDK和Azure搜索REST API都没有提供自行订购方面的方法,但请记住,您最终可以完全控制在UI中显示方面信息的方式。如果SDK未提供您所需的内容,您可以在应用中创建一个简单的查找类,以便根据需要订购方面。像这样:

public class FacetDefinition
{
    public string FacetName { get; set; }
    public int FacetOrder { get; set; }
}

...

var myFacetDefinitions = new List<FacetDefinition>();
myFacetDefinitions.Add(new FacetDefinition() { FacetName = "SomeNameThatMatchesTheFacetThatAzureSearchSendsBack", FacetOrder = 1});
myFacetDefinitions.Add(new FacetDefinition() { FacetName = "SomeOtherNameThatMatchesTheFacetThatAzureSearchSendsBack", FacetOrder = 2});
...

子弹#4回答:

要返回特定用户的所有图书,您只需添加如下过滤器表达式:

userId eq <put_authenticated_userid_here>

假设当前经过身份验证的用户应该只能看到自己的图书。但是,如果您希望能够在构面中包含一个用户列表来过滤其中的一个或多个,那么需要对索引架构进行另一种重新构建,以便在书籍文档中创建一个名为“users”是用户名的Collection(Edm.String)。像这样:

{
    ...
    users: ["Luke Skywalker", "Han Solo", "Chewbacca", etc...]
    ...
}