我正在使用 Azure DocumentDB 存储有关用户的信息。这些文档包含一个名为date_created的属性。我想向 documentDB 发送查询以检索存储在此集合中的所有用户。我还希望结果从最新到最旧排序。
我目前在 DocumentDB 中实现了一个存储过程,它遍历集合并根据日期属性对结果进行排序。但是,我有两个问题:
- 返回多个文档进行查询时,DocumentDB 使用的默认排序是什么?
我知道 DocumentDB 尚不支持排序控制,但如果我使用存储过程对结果进行排序,我是在执行完整的集合扫描,还是数据库至少利用了我正在排序的属性的索引?有关信息,我正在使用的存储过程是这个(根据产品团队提供的 Azure 示例稍作修改):
function orderBy(filterQuery, orderByFieldName, continuationToken) { // HTTP error codes sent to our callback funciton by DocDB server. var ErrorCode = { REQUEST_ENTITY_TOO_LARGE: 413, } var collection = getContext().getCollection(); var collectionLink = collection.getSelfLink(); var result = new Array(); tryQuery({}); function tryQuery(options) { var isAccepted = (filterQuery && filterQuery.length) ? collection.queryDocuments(collectionLink, filterQuery, options, callback) : collection.readDocuments(collectionLink, options, callback) if (!isAccepted) throw new Error("Source dataset is too large to complete the operation."); } /** * queryDocuments callback. * @param {Error} err - Error object in case of error/exception. * @param {Array} queryFeed - array containing results of the query. * @param {ResponseOptions} responseOptions. */ function callback(err, queryFeed, responseOptions) { if (err) { throw err; } // Iterate over document feed and store documents into the result array. queryFeed.forEach(function (element, index, array) { result[result.length] = element; }); if (responseOptions.continuation) { // If there is continuation, call query again providing continuation token. tryQuery({ continuation: responseOptions.continuation }); } else { // We are done with querying/got all results. Sort the results and return from the script. result.sort(compare); fillResponse(); } } // Compare two objects(documents) using field specified by the orderByFieldName parameter. // Return 0 if equal, -1 if less, 1 if greater. function compare(x, y) { if (x[orderByFieldName] == y[orderByFieldName]) return 0; else if (x[orderByFieldName] < y[orderByFieldName]) return 1; return -1; } // This is called in the very end on an already sorted array. // Sort the results and set the response body. function fillResponse() { var page_size = 20; // Main script is called with continuationToken which is the index of 1st item to start result batch from. // Slice the result array and discard the beginning. From now on use the 'continuationResult' var. var continuationResult = result; if (continuationToken) continuationResult = result.slice(continuationToken); else continuationToken = 0; if (page_size > continuationResult.length ) { page_size = continuationResult.length; } // Get/initialize the response. var response = getContext().getResponse(); response.setBody(null); // Take care of response body getting too large: // Set Response iterating by one element. When we fail due to MAX response size, return to the client requesting continuation. var i = 0; var final_result = []; for (; i < page_size; ++i) { try { // Note: setBody is very expensive vs appendBody, use appendBody with simple approximation JSON.stringify(element). final_result.push(continuationResult[i]); } catch (ex) { if (!ex.number == ErrorCode.REQUEST_ENTITY_TOO_LARGE) throw ex; break; } } /* Now next batch to return to client has i elements. // Slice the continuationResult if needed and discard the end. */ var partialResult = continuationResult; var newContinuation = null; if (i < continuationResult.length) { partialResult = continuationResult.slice(0, i); } // Finally, set response body. response.setBody({ result: final_result, continuation: i }); }
}