Вот что у меня есть и что я хочу сделать
У меня есть Cosmos DB с контейнером, давайте назовем контейнер "Проекты". В этом контейнере у меня есть сотни проектных документов, которые имеют следующую структуру (пример в json):
{
"name": "Death Star - Software update",
"number": "133701",
"customer" : ""
}
Чтобы сделать данные доступными для любого типа клиента, я использую http-триггер azure функция (. Net Core 2.1). Функция azure имеет входную привязку к базе данных cosmos, несколько механизмов безопасности и ожидает один или несколько параметров get, называемых «Поиск», поэтому URL запроса может выглядеть следующим образом:
https://www.someUrlToMyAzureStuff.com/api/GetProjects?Search=Death&Search=update
Идея состоит в том, что функция позволяет выполнять поиск по ключевым словам, и то, что когда-либо проект содержит эти ключевые слова в своих свойствах, будет возвращено.
Вот краткий пример кода для функции azure:
[FunctionName("GetProjects")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest request,
[CosmosDB(databaseName: "ProjectsDatabase", collectionName: "ProjectsContainer",
ConnectionStringSetting = "someConnectionString")] DocumentClient projectsContainer,
ILogger log)
{
try
{
if (CheckSecurityStuff...)
{
// The httpGetParameters contains a List<string> that contains the "Search" Get parameters from the Url
var httpGetParameters = RESTUtility.RetrieveHttpGetParametersFromRequest(request);
var projects = await CosmosDataProvider.GetProjectsByFiltersAsync(projectsContainer, httpGetParameters.UrlParams);
return new OkObjectResult(projects);
}
else
{
return new BadRequestResult();
}
}
catch (Exception)
{
return new BadRequestResult();
}
}
И вот функция CosmosDataProvider.GetProjectsByFiltersAsyn c, где я сталкиваюсь со странным поведением:
internal static async Task<List<Project>> GetProjectsByFiltersAsync(DocumentClient projectsContainer, List<string> filters)
{
return await Task.Run(() =>
{
var uri = UriFactory.CreateDocumentCollectionUri("ProjectsDatabase", "ProjectsContainer");
var feedOptions = new FeedOptions { EnableCrossPartitionQuery = true };
var projects = projectsContainer.CreateDocumentQuery<Project>(uri, feedOptions)
.Where(project => project.Name.Contains(filters[0]) ||
project.Number.Contains(filters[0]) ||
project.Customer.Contains(filters[0])).ToList();
foreach (var filter in filters.Skip(1))
{
projects = projects.Where(project =>
project.Name.Contains(filter) ||
project.Number.Contains(filter) ||
project.Customer.Contains(filter)).ToList();
}
return projects;
}
}
Пока все хорошо: если я отправлю запрос с параметрами поиска «Смерть» и «обновление», функция вернет вышеупомянутый проект. Который работает нормально, но возвращается только тогда, когда ключевые слова соответствуют регистру. Так что я хочу сделать поиск, игнорируя случай. Поэтому я начал использовать:
Contains(string, StringComparison)
с StringComparison.OrdinalIgnoreCase. Что выглядит следующим образом:
internal static async Task<List<Project>> GetProjectsByFiltersAsync(DocumentClient projectsContainer, List<string> filters)
{
return await Task.Run(() =>
{
var uri = UriFactory.CreateDocumentCollectionUri("ProjectsDatabase", "ProjectsContainer");
var feedOptions = new FeedOptions { EnableCrossPartitionQuery = true };
var projects = projectsContainer.CreateDocumentQuery<Project>(uri, feedOptions)
.Where(project => project.Name.Contains(filters[0], StringComparison.OrdinalIgnoreCase) ||
project.Number.Contains(filters[0], StringComparison.OrdinalIgnoreCase) ||
project.Customer.Contains(filters[0], StringComparison.OrdinalIgnoreCase)).ToList();
foreach (var filter in filters.Skip(1))
{
projects = projects.Where(project =>
project.Name.Contains(filter) ||
project.Number.Contains(filter) ||
project.Customer.Contains(filter)).ToList();
}
return projects;
}
}
Я ожидаю, что я ищу «смерть» и «uPdAte» и получаю проект. Но Cosmos DB не возвращает его.
Вопросы
-> Есть ли у вас какие-либо идеи, почему StringComparison не работает в условии CreateDocumentQuery where?
-> Так как Contains (строка, StringComparison) доступна только в. Net Core, это может быть конфликт с Azure SDK. Net, который может использовать. Net Framework ?
(Между прочим: я также попытался заменить функцию «Contains» на «IndexOf» или «RegEx.IsMatch», оба не сработали, за исключением того, что они не поддерживаются в операторе LINQ Where) Сведения об исключении:
One or more errors occurred. (Method 'IndexOf' is not supported., Windows/10.0.18363 documentdb-netcore-sdk/2.3.0)
-> Любая другая идея, как я могу заменить функцию содержит, если нет решения?