DocumentDb 中的形状不正确 Select

Not Getting the Shape Right in DocumentDb Select

我试图在 SELECT 查询中仅获取此人的会员信息,即 ID、姓名和委员会会员资格。这是我的对象:

{
   "id": 123,
   "name": "John Smith",
   "memberships": [
      {
          "id": 789,
          "name": "U.S. Congress",
          "yearElected": 2012,
          "state": "California",
          "committees": [
             {
                 "id": 444,
                 "name": "Appropriations Comittee",
                 "position": "Member"
             },
             {
                 "id": 555,
                 "name": "Armed Services Comittee",
                 "position": "Chairman"
             },
             {
                 "id": 678,
                 "name": "Veterans' Affairs Comittee",
                 "position": "Member"
             }
          ]
      }
   ]
}

在此示例中,John Smith 是 U.S 的成员。国会和其中的三个委员会。

我尝试获得的结果应该如下所示。同样,这是 "DESIRED RESULT":

{
   "id": 789,
   "name": "U.S. Congress",
   "committees": [
      {
         "id": 444,
         "name": "Appropriations Committee",
         "position": "Member"
      },
      {
         "id": 555,
         "name": "Armed Services Committee",
         "position": "Chairman"
      },
      {
         "id": 678,
         "name": "Veterans' Affairs Committee",
         "position": "Member"
      }
   ]
}

这是我的 SQL 查询:

SELECT m.id, m.name, 
[ 
    {
        "id": c.id,
        "name": c.name,
        "position": c.position
    }
] AS committees
FROM a 
JOIN m IN a.memberships
JOIN c IN m.committees
WHERE a.id = "123"

我得到以下正确的结果,但形状不正确。我获得了 3 次相同的会员资格。这是我得到的结果,这不是我想要的结果:

[
 {
   "id": 789,
   "name": "U.S. Congress",
   "committees":[
      {
         "id": 444,
         "name": "Appropriations Committee",
         "position": "Member"
      }
   ]
 },
 {
   "id": 789,
   "name": "U.S. Congress",
   "committees":[
      {
         "id": 555,
         "name": "Armed Services Committee",
         "position": "Chairman"
      }
   ]
 },
 {
   "id": 789,
   "name": "U.S. Congress",
   "committees":[
      {
         "id": 678,
         "name": "Veterans' Affairs Committee",
         "position": "Member"
      }
   ]
 }
]

如您所见,"U.S. Congress" 成员资格重复了 3 次。

下面的 SQL 查询在 Azure 查询资源管理器中得到了我想要的东西,但是当我在我的代码中将它作为查询传递时——使用 DocumentDb SDK——我没有得到任何细节对于委员会。我只是得到委员会 ID、姓名和职位的空白结果。但是,我确实获取了会员数据,即 "U.S. Congress",等等。这是 SQL 查询:

SELECT m.id, m.name, m.committees AS committees 
FROM c 
JOIN m IN c.memberhips 
WHERE c.id = 123

我包括了调用 DocumentDb 的代码。我将代码包含在我们的内部评论中以帮助阐明它们的目的:

首先是我们需要从 DocumentDb 中读取内容时调用的 ReadQuery 函数:

public async Task<IEnumerable<T>> ReadQuery<T>(string collectionId, string sql, Dictionary<string, object> parameterNameValueCollection)
{
   // Prepare collection self link
   var collectionLink = UriFactory.CreateDocumentCollectionUri(_dbName, collectionId);

   // Prepare query
   var query = getQuery(sql, parameterNameValueCollection);

   // Creates the query and returns IQueryable object that will be executed by the calling function
   var result = _client.CreateDocumentQuery<T>(collectionLink, query, null);

   return await result.QueryAsync();
}

以下函数使用任何参数准备查询:

protected SqlQuerySpec getQuery(string sql, Dictionary<string, object> parameterNameValueCollection)
{
   // Declare query object
   SqlQuerySpec query = new SqlQuerySpec();

   // Set query text
   query.QueryText = sql;

   // Convert parameters received in a collection to DocumentDb paramters
   if (parameterNameValueCollection != null && parameterNameValueCollection.Count > 0)
   {
      //  Go through each item in the parameters collection and process it
      foreach (var item in parameterNameValueCollection)
      {
         query.Parameters.Add(new SqlParameter($"@{item.Key}", item.Value));
      }
   }

   return query;
}

此函数对 DocumentDb 进行异步调用:

public async static Task<IEnumerable<T>> QueryAsync<T>(this IQueryable<T> query)
{
   var docQuery = query.AsDocumentQuery();

   // Batches gives us the ability to read data in chunks in an asyc fashion.
   // If we use the ToList<T>() LINQ method to read ALL the data, the call will synchronous which is why we prefer the batches approach.
   var batches = new List<IEnumerable<T>>();

   do
   {
      // Actual call is made to the backend DocumentDb database
      var batch = await docQuery.ExecuteNextAsync<T>();
      batches.Add(batch);
   }

   while (docQuery.HasMoreResults);

  // Because batches are collections of collections, we use the following line to merge all into a single collection.
  var docs = batches.SelectMany(b => b);

  // Return data
  return docs;
}

我刚刚编写了一个演示来测试您的查询,我可以得到预期的结果,请查看下面的快照。所以我认为该查询是正确的,您已经提到当您在我的代码中进行调用时似乎没有获得任何数据,您介意分享您的代码吗?也许您的代码中存在一些错误。总之,这是我的测试,仅供参考,希望对您有所帮助。

使用的查询

SELECT m.id AS membershipId, m.name AS membershipNameName, m.committees AS committees 
FROM c 
JOIN m IN c.memberships 
WHERE c.id = "123"

这里的代码很简单,sp_db.innerText代表一个span,我在测试页中用来显示结果:

var docs = client.CreateDocumentQuery("dbs/" + databaseId + "/colls/" + collectionId,
"SELECT m.id AS membershipId, m.name AS membershipName, m.committees AS committees " +
"FROM c " +
"JOIN m IN c.memberships " +
"WHERE c.id = \"123\"");
        foreach (var doc in docs)
        {
            sp_db.InnerText += doc;
        }

我认为您在 client.CreateDocumentQuery() 中指定的查询可能有一些拼写错误,导致结果为 none,最好为我们提供代码,然后我们可以帮助检查它。

更新:
刚刚尝试了您的代码,但我仍然可以获得预期的结果。我发现的一件事是,当我指定像 "where c.id = \"123\"" 这样的 where 子句时,它会得到结果:

但是,如果你没有逃脱,只是使用"where c.id = 123",这次你什么也得不到。我认为这可能是一个原因。您可以验证您是否运行进入这种情况。

刚刚更新了我的原创post。问题中提供的所有代码都是正确且有效的。我遇到了问题,因为我在 SELECT 查询中使用了别名,结果某些属性没有绑定到我的域对象。

题中提供的代码是正确的。