【问题标题】:How to search on Cosmos DB in a complex JSON Object如何在复杂的 JSON 对象中搜索 Cosmos DB
【发布时间】:2020-04-25 17:41:52
【问题描述】:

我有以下 JSON 对象,你可以看到它引用了一个 TAG 对象,它是一个标签数组。

public class GlobalPageTemplate : ISharedCosmosEntity
{
    [JsonProperty("Id")]
    public string Id { get; set; }

    [CosmosPartitionKey]
    public string CosmosEntityName { get; set; }

    public string Description { get; set; }
    public string ExtractedPageName { get; set; }
    public string ExtractedSitecollectionTemplateName { get; set; }
    public string ExtractedGlobalDesignTenantId { get; set; }
    public string ExtractedGlobalDesigntenantSiteCollectionUrl { get; set; }
    public string PageTemplatePictureUrl { get; set; }
    public string Base64Image { get; set; }
    public string PageTemplateName { get; set; }
    public List<Section> Sections { get; set; }
    public string TemplateAccessLevel { get; set; }
    public List<Tag> Tags { get; set; }
}

public class Tag : ISharedCosmosEntity
{

    [JsonProperty("Id")]
    public string Id { get; set; }

    public string TagName { get; set; }

    [CosmosPartitionKey]
    public string CosmosEntityName { get; set; }
}

在数据库中,对象是这样保存的:

{
    "CosmosEntityName": "globalpagetemplates",
    "Description": "depper",
    "ExtractedPageName": "Home.aspx",
    "ExtractedSitecollectionTemplateName": "CommunicationSite",
    "ExtractedGlobalDesignTenantId": "696da7e7-a03e-4996-bbf8-625b8e4c4c06",
    "ExtractedGlobalDesigntenantSiteCollectionUrl": "https://xx.sharepoint.com/sites/TST1",
    "PageTemplatePictureUrl": "https://xx.blob.core.windows.net/globalpagetemplatespictures/0befc979-3958-4e27-a345-f4ce491eb1ee.png",
    "Base64Image": "",
    "PageTemplateName": "Plantilla 5 TST 1",
    "Sections": [],
    "TemplateAccessLevel": "Platinum",
    "Tags": [
        {
            "Id": null,
            "TagName": "recursos humanos",
            "CosmosEntityName": null
        }
    ],
    "id": "0befc979-3958-4e27-a345-f4ce491eb1ee",
    "_rid": "q6JzALvx8ZHMCQAAAAAAAA==",
    "_self": "dbs/q6JzAA==/colls/q6JzALvx8ZE=/docs/q6JzALvx8ZHMCQAAAAAAAA==/",
    "_etag": "\"35001a26-0000-0300-0000-5df77cf60000\"",
    "_attachments": "attachments/",
    "_ts": 1576500470
}

我有一个返回所有页面模板的方法:

/// <returns></returns>
[HttpGet]
public async Task<IHttpActionResult> GetGlobalPageTemplates()
{ 
    var telemetry = new TelemetryClient();
    try
    {
        var globalPageTemplateStore = CosmosStoreHolder.Instance.CosmosStoreGlobalPageTemplate;
        var globalPageTemplates =  await globalPageTemplateStore.Query().ToListAsync();
        return Ok(globalPageTemplates);
    }
    catch (Exception ex)
    {
        string guid = Guid.NewGuid().ToString();
        var dt = new Dictionary<string, string>
        {
            { "Error Lulo: ", guid }
        };

        telemetry.TrackException(ex, dt);
        return BadRequest("Error Lulo: " + guid);
    }
}

但是在前端我可以过滤标签,

所以我需要创建一个接收字符串列表的方法,然后进行查询以获取与 TAGS 匹配的页面模板,过滤器应该是独占的,我的意思是 OR。

/// <returns></returns>
[HttpGet]
public async Task<IHttpActionResult> GetGlobalPageTemplatesByTags(List<string> tags)
{ 
    var telemetry = new TelemetryClient();
    try
    {
        var globalPageTemplateStore = CosmosStoreHolder.Instance.CosmosStoreGlobalPageTemplate;
        var globalPageTemplates =  await globalPageTemplateStore.Query().Where???
    }
    catch (Exception ex)
    {
        string guid = Guid.NewGuid().ToString();
        var dt = new Dictionary<string, string>
        {
            { "Error Lulo: ", guid }
        };

        telemetry.TrackException(ex, dt);
        return BadRequest("Error Lulo: " + guid);
    }
}

知道如何实现吗?

【问题讨论】:

    标签: c# asp.net .net linq azure-cosmosdb


    【解决方案1】:

    您可以使用来自 LINQ 的 Where()Any()Contains() 尝试此查询:

    var globalPageTemplates = await globalPageTemplateStore
        .Query()
        .Where(template => template
            .Tags
            .Any(tag => tags.Contains(tag.TagName))
         )
         .ToListAsync();
    

    如果您想更快地查找 tags,我建议您将其转换为 HashSet&lt;string&gt;

    var tagLookups = new HashSet<string>(tags);
    
    var globalPageTemplates = await globalPageTemplateStore
        .Query()
        .Where(template => template
            .Tags
            .Any(tag => tagLookups.Contains(tag.TagName))
        )
        .ToListAsync();
    

    基本思路是先用Where()过滤每个模板,然后用Contains()检查tags中是否存在模板标签中的Any()

    注意:您必须在查询末尾添加ToListAsync(),才能将IQueryable&lt;GlobalPageTemplate&gt; 转换为List&lt;GlobalPageTemplate&gt;。这是因为查询是异步的。

    【讨论】:

      【解决方案2】:

      我相信,您正在寻找一种解决方案来过滤 GlobalPageTemplateTagName 中的 List&lt;string&gt; tags 匹配;如果是,您可以将.Where.Any.ContainsList 一起使用

      Sample Code

      var globalPageTemplateStore = CosmosStoreHolder.Instance.CosmosStoreGlobalPageTemplate;
      var globalPageTemplates =  await globalPageTemplateStore.Query()
          .Where(.Where(c => c.Addresses.Any(a => cityList.Contains(a.City)))
          .ToList();
      

      注意:这仅适用于Client Evaluation,您可能需要使用.AsEnumerable

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-27
        • 2015-08-02
        相关资源
        最近更新 更多