【问题标题】:Is it possible to populate a collection in an Azure Search index?是否可以在 Azure 搜索索引中填充集合?
【发布时间】:2019-12-18 22:04:24
【问题描述】:

我目前一直在使用 Azure 搜索,我偶然发现了一个场景,其中我有两张表:一张描述一个地点,另一张为每个地点提供多张照片。

我想使用两个索引器来填充相同的索引,其中一个会填充地点的详细信息(名称、坐标等),而另一个会获取照片,运行自定义 WebApiSkill,从照片,并将它们添加到索引上的复杂集合中。

问题是,我不知道如何在索引中填充该照片集。我尝试将我的outputFieldMappings 定义为Photos/*/Details,或者只是Photos/Details,但我一直收到同样的错误:

Microsoft.Rest.Azure.CloudException: 'Output field mapping specifies target field 'Photos/*/PhotoURI' that doesn't exist in the index'

考虑到这一点,我想知道是否可以在 Azure 搜索中填充这样的复杂集合,如果可以,我将如何去做?


表格:

CREATE TABLE Places
(
    Id             bigint         not null  IDENTITY(1,1)  PRIMARY KEY,
    Name           nvarchar(50)   not null,
    Location       nvarchar(50)   not null
);

CREATE TABLE PlacePhotos
(
    PhotoURI  nvarchar(200)  not null  PRIMARY KEY,
    PlaceId   bigint         not null  REFERENCES Places (Id)
);

用于创建索引的类:

public partial class Photo
{
    [IsSearchable]
    public string PhotoURI { get; set; }

    public List<Details> Details { get; set; }
}
public partial class Place
{
    [System.ComponentModel.DataAnnotations.Key]
    public string Id { get; set; }

    [IsSearchable, IsFilterable, IsSortable, IsFacetable]
    public string Name { get; set; } 

    [IsSearchable, IsFilterable]
    public string Location { get; set; }

    [IsSearchable, IsFilterable, IsSortable]
    public List<Photo> Photos { get; set; }

}

索引器(以PlacePhotos 表作为其数据源):

private static void Create_PlacePhotos_Indexer(SearchServiceClient serviceClient)
{
    var indexerDef = new Indexer(
        name: placePhotosIndexer,
        dataSourceName: placePhotosDataSource,
        targetIndexName: index,
        skillsetName: skillset,
        schedule: new IndexingSchedule
        {
            Interval = new TimeSpan(0, 30, 0)
        },
        fieldMappings: new List<FieldMapping>
        {
            new FieldMapping("PlaceId", "Id"),
            new FieldMapping("PhotoURI", "PhotoURI")
        },
        outputFieldMappings: new List<FieldMapping>
        {
            new FieldMapping("/document/Id", "Id"),
            new FieldMapping("/document/PhotoURI", "Photos/*/PhotoURI"),
            new FieldMapping("/document/Details", "Photos/*/Details")
        }
    );
    serviceClient.Indexers.CreateOrUpdate(indexerDef);
}

【问题讨论】:

    标签: c# azure indexing azure-sql-database azure-cognitive-search


    【解决方案1】:

    Output field mapping目标字段名必须是顶级索引字段名,所以Photos/*/PhotoURI无效,必须直接定位Photos

    要“塑造”要映射的Photos 值,您可以使用ShaperSkill

    {
      "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
      "context": "/document/photos/*",
      "inputs": [
        {
          "name": "PhotoURI",
          "source": "/document/photos/*/PhotoURI"
        },
        {
          "name": "Details",
          "source": "/document/photos/*/Details"
        }
      ],
      "outputs": [
        {
          "name": "output",
          "targetName": "shapedValue"
        }
      ]
    }
    

    和输出字段映射

    new FieldMapping("/document/photos/*/shapedValue", "Photos")
    

    注意 - 您可能需要重新排列输出 URI 和详细信息的技能,以便它们共享一个共同的 context。从您上面的 sn-p 看来,每个 document 只有一张照片,这与您的索引定义不同。

    【讨论】:

    • 感谢您的回答。只有一个细节我不明白:这样的映射会有效地填充复杂的字段吗?如果我从多张照片中生成多个值到 photos 字段中,它们仍然会在每次重写时覆盖该字段,不是吗?
    • Place 类定义了public List&lt;Photo&gt; Photos,所以Photos 是一个复杂类型的集合,并且需要一个Photos 的数组。
    • 这是否意味着多个Photos 可以映射到集合而不会相互覆盖?
    • class Place 中定义的顶级Photos 必须是唯一的(每个文档1 个),但每个Photos 值可以包含零个或多个class Photo 值(并且每个@987654341 @ 将被存储而不被覆盖)。由于Photos 被定义为List&lt;Photo&gt; Photos,它对应于索引字段类型Collection(Edm.ComplexType) - 参见docs.microsoft.com/en-us/rest/api/searchservice/…
    • 所以他们不会互相覆盖……那是我的恐惧。谢谢你的解释!
    猜你喜欢
    • 2017-05-24
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 2021-01-11
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多