【问题标题】:Not all properties are mapped while querying Azure Cosmos DB查询 Azure Cosmos DB 时并非所有属性都已映射
【发布时间】:2018-07-17 12:56:29
【问题描述】:

我希望将 Azure CosmosDB 集成到我们的项目中。我为自己设定的目标是创建一个常见问题解答部分。我已经创建了表格,还添加了三个带有一些示例数据的集合。但是,在查询时,我可以看到并非所有属性都是从 JSON 开始映射的,因此我的查询没有给出任何结果。

我的模型类看起来像这样;

BasisDocumentDBEntity

//This is a base class with some common shared properties
public abstract class BasisDocumentDBEntity
{
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    [JsonProperty(PropertyName = "AangemaaktDoor")]
    public string AangemaaktDoor { get; set; }

    [JsonProperty(PropertyName = "AangemaaktOp")]
    public DateTime AangemaaktOp { get; set; }

    [JsonProperty(PropertyName = "GewijzigdOp")]
    public DateTime GewijzigdOp { get; set; }

    [JsonProperty(PropertyName = "GewijzigdDoor")]
    public string GewijzigdDoor { get; set; }
}

常见问题组

//I've came up with groups for FAQ. A group for example can be 'General' or 'Instruction video's'
public class FAQGroup : BasisDocumentDBEntity
{
    [JsonProperty(PropertyName = "Name")]
    public string Naam { get; set; }

    [JsonProperty(PropertyName = "Sections")]
    public List<FaqSection> Sections { get; set; }
}

常见问题部分

//Each group can contain one or more sections. And each section can contain one or more questions.
public class FaqSection : BasisDocumentDBEntity
{
    [JsonProperty(PropertyName = "Title")]
    public string Title { get; set; }

    [JsonProperty(PropertyName = "GroupId")]
    public string GroupId { get; set; }

    public FAQGroup Group { get; set; }

    [JsonProperty(PropertyName = "Questions")]
    public List<FAQQuestion> Questions { get; set; }
}

常见问题解答

//The actual question with the answer in it.
public class FAQQuestion : BasisDocumentDBEntity
{
    [JsonProperty(PropertyName = "Question")]
    public string Question { get; set; }

    [JsonProperty(PropertyName = "Answer")]
    public string Answer { get; set; }
}

我知道 CosmosDB 不是关系数据库类型。但是,如果我正确理解this article,它应该是有可能的。

我的示例数据像这样存储在 CosmosDB 中;

组:

{
"id": "1",
"Name": "Group 1",
"Sections": [
    1,
    2,
    3
],
"AangemaaktDoor": "user",
"AangemaaktOp": "2018-07-17 08:46",
"GewijzigdDoor": "user",
"GewijzigdOp": "2018-07-17 08:46",
"_rid": "<snip>",
"_self": "<snip>",
"_etag": "<snip>",
"_attachments": "attachments/",
"_ts": 1531818056
}

部分:

{
"id": "1",
"GroupId": "1",
"Title": "Common",
"Questions": [
    1,
    2,
    3
],
"AangemaaktDoor": "user",
"AangemaaktOp": "2018-07-17 08:46",
"GewijzigdDoor": "user",
"GewijzigdOp": "2018-07-17 08:46",
"_rid": "<snip>",
"_self": "<snip>",
"_etag": "<snip>",
"_attachments": "attachments/",
"_ts": 1531810510
}

问题:

{
"id": "1",
"Question": "My First Question is?",
"Answer": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ultrices convallis sapien, sed vestibulum nisl mollis eget. Sed feugiat aliquet orci. Sed pretium feugiat enim, nec lacinia lacus eleifend et. Morbi vitae risus cursus sapien sodales ullamcorper id ut eros. Cras semper ipsum at congue tempus. Fusce hendrerit lorem lorem, non fermentum purus vehicula vel. Nulla aliquam lorem turpis, venenatis hendrerit ligula efficitur eget. Curabitur et erat quis diam interdum vestibulum. Proin congue feugiat dui, a feugiat nisi bibendum eget. Etiam congue orci eget magna efficitur semper. Sed mattis posuere ex, ut venenatis augue condimentum ac. Etiam tincidunt est odio, vitae interdum nibh mollis a. Aliquam id hendrerit dui, et bibendum justo. In hac habitasse platea dictumst.",
"AangemaaktDoor": "user",
"AangemaaktOp": "2018-07-17 08:46",
"GewijzigdDoor": "user",
"GewijzigdOp": "2018-07-17 08:46",
"_rid": "<snip>",
"_self": "<snip>",
"_etag": "<snip>",
"_attachments": "attachments/",
"_ts": 1531810570
}

我在微软文档中使用this article 作为参考。但我无法弄清楚为什么有些属性被填充而有些则没有。这就是我从存储库中返回的内容;

GroupId 和 Title 字段均不包含任何数据。我无法理解它。感觉很明显。有人知道吗?

更新

    public static async Task<IEnumerable<T>> GetItemsAsync(Expression<Func<T, bool>> 
predicate)
            {
            if (!_isInitialized) throw new InvalidOperationException("Repository must be initialized first!");

            //Query with filter >> returns nothing
            IDocumentQuery<T> query = _client.CreateDocumentQuery<T>(
                UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId),
                new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true })
                .Where(predicate)
                .AsDocumentQuery();

            //Query without filter >> returns list with single section but empty 'GroupId' and empty 'Title'
            var xquery = _client.CreateDocumentQuery<T>(
            UriFactory.CreateDocumentCollectionUri(_databaseId, _collectionId),
            new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true })
            .ToList();

            List<T> results = new List<T>();
            while (query.HasMoreResults)
            {
                results.AddRange(await query.ExecuteNextAsync<T>());
            }

            return results;
        }

更新 2

    public async Task<SectionDTO> GetFAQOverzicht(EFaqGroup faqGroup)
    {
        var faqSection = new SectionDTO();

        var groupId = ((int) faqGroup).ToString();
        var section = await DocumentDBRepository<FaqSection>.GetItemsAsync(faq => faq.GroupId == groupId);

        return faqSection;
    }

【问题讨论】:

  • 您确定从正确的集合中提取数据吗?
  • 您是如何查询这些数据的?您要加入 CosmosDB SQL 吗?您是否正在执行多个查询来获取对象?
  • @NickChapsas,我很快就会用查询更新问题。我知道我需要进行连接或多个查询才能完成任务。但目前的问题是两个必填字段“GroupId”和“Title”不包含任何数据。即使在我的测试集中它们已经被填满了。

标签: c# azure azure-cosmosdb azure-cosmosdb-sqlapi


【解决方案1】:

CosmosDB 不是您所说的关系数据库。您使用的 CosmosDB SDK 不是 ORM。它只是 CosmosDB API 的一个包装器。

这意味着除非您使用连接或执行多个查询来进行检索,否则您不能只从它们各自的集合中获取其他对象。

仅仅因为您有一个包含数字的 GroupId 属性并不意味着 Section 集合与 Group 集合有任何关系。它不是实体框架。对于 CosmosDB 和 SDK,它们只是两个独立的集合,它们之间没有任何关系。

为了执行您想要的操作,您要么需要执行多个查询来填充您正在检索的对象(不推荐每个子对象一个),要么使用 CosmosDB SQL 连接到其他两个表并映射检索到的结果到你的对象。

【讨论】:

  • 我明白这一点,这完全有道理。但我目前的问题是我想用来加入的字段不包含任何数据。 “GroupId”和“Title”字段为空,我不明白为什么。
  • 你能告诉我GetItemsAsync方法调用吗?我怀疑您查询的是 QuestionGroup 对象,这是唯一没有这两个属性的对象
  • 我已经用代码再次更新了问题。我理解你的意思,但目前我正在查询该部分。
  • @Rob 但是你在代码中的什么地方限制了它?仅将 T 参数传递给 CreateDocumentQuery 方法不会将其限制为这些对象。 SDK 中没有这个逻辑。这是一个映射指令。您基本上告诉它返回它拥有的任何Document,并尝试将其映射到T 参数上。 CosmosDB 与类型无关,因此除非您明确告诉它您想要什么,否则它将返回所有内容。
  • @Rob 我实际上必须在我为 CosmosDB 编写的 ORM Cosmonaut 中编写此功能,因为 SDK 不支持它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-17
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多