LINQ запрос с несколькими содержит / любой для Ravendb

StackOverflow https://stackoverflow.com/questions/4207739

  •  25-09-2019
  •  | 
  •  

Вопрос

У меня есть класс документа, который содержит список «тегов». Что-то типа:

class Item {
  string Name { get; set; }
  List<string> Tags {get; set;}
}

Теперь я хотел бы создать запрос для Ravendb, который вручает мне все предметы, фильтрованные списком тегов. При использовании Entity Framework мне удалось сделать это чем-то вроде этого:

var query = GetQueryable();
foreach (var tag in tags)
{
   query = query.Where(i => i.Tags.Contains(tag));
}

Однако, похоже, это не работает с RavendB, скорее всего, потому что содержится не поддерживается .. Я также пытался переписать его, используя любые, (Where(i => i.Tags.Any(t=>t == tag))) Но это дает мне странное исключение:

Unable to cast object of type
'System.Linq.Expressions.PrimitiveParameterExpression`1[System.String]'
to type 'System.Linq.Expressions.MemberExpression

Любые отличные идеи? Я делаю это совершенно не так?

Это было полезно?

Решение

Содержится действительно не поддерживается (возможно, должно быть, но это другое дело полностью - мы действительно добавляем поддержку различных операторов, когда его просили)

Что касается нескольких запросов против любого, я предполагаю, что вы пытаетесь сделать динамические данные, и вы хотите достичь чего-то вроде

"X OR Y OR Z"

Это сложно, и поставщик LINQ по умолчанию будет совокупным этими кратным ключам, и, поэтому ваш пример выглядит как

"X AND Y AND Z"

Что, очевидно, никогда не будет так.

Ваш лучший вариант для этого - это упасть на запрос Lucene (по крайней мере, на данный момент) и сделать что-то подобное:

var results = s.Advanced.LuceneQuery<Item>()
                   .Where(string.Format("Tags,:({0})", string.Join(" OR ", tags))); 

Иметь смысл?

Запрос выше будет выглядеть что-то вроде

"Tags,:(X OR Y OR Z)"

Примечание: «Метки» сообщает Ravendb, что теги - это массив

Хорошо, [править]!

Самый простой способ получить то, что вы на самом деле хочу это сделать что-то вдоль этих линий

                new IndexDefinition<Item, Item>()
                {
                    Map = docs => from doc in docs
                                  select new
                                  {
                                      Tags = doc.Tags
                                  },
                    Indexes = {{ x => x.Tags, FieldIndexing.Analyzed }}
                }.ToIndexDefinition(store.Conventions));

Затем, чтобы запросить ваше и свое, вы можете сделать что-то вроде этого:

                var results = s.Advanced.LuceneQuery<Item, WhateverYouCalledThatIndex>()
                   .Where(string.Format("Tags:({0})", string.Join(" AND ", tags)));

Теперь, что нужно знать о

       Tags = doc.Tags

Будет сериализовать этот целый массив в один гигантский BLOB, так как это просто строки, которые будут работать на этот пример.

Я смотрю на лучшие способы выражения этого, маловероятно, что мы придумаем Linq-ish-способ сделать это, так как он не очень хорошо настроен на очень хорошо - но это является Ответ, который будет работать :)

Я думаю, что я бы хотел иметь возможность хотя бы сделать

  Map = docs => from doc in docs
                                  select new
                                  {
                                      Tags = String.Join(" ", doc.Tags)
                                  },

(Это не будет работать, так что не попробуйте), но немного более четко о том, что вы хотите достичь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top