Выберите элементы по тегу при поиске нескольких тегов - PullRequest
0 голосов
/ 22 января 2009

Я немного борюсь здесь, поэтому подумал, почему бы не спросить:

Каждая сущность в моей системе имеет список тегов (список строк), и я хочу иметь возможность искать несколько тегов одновременно.

У меня есть IQueryable для работы. У каждой сущности есть IList с именем Tags, а моим входным параметром является IList.

Я мог бы просто пройтись по всем тегам и сделать IQueryable.Where (p => p.Tags.Contains (currentTag), но это не очень хорошо масштабируется со многими тегами в качестве входных данных, а также у меня есть ощущение, что это может быть сделано внутри LinQ.

Надеюсь, у кого-нибудь есть идея.

Редактировать: Уточнение вопроса: Я ищу способ выбрать только элементы из моего IQueryable, которые содержат ВСЕ предоставленные теги параметров (из IList).

привет Даниил / Тигрэйн

Ответы [ 2 ]

2 голосов
/ 22 января 2009

С здесь , это какой-то sql, который будет работать для вас:

SELECT entityID
FROM tags
WHERE tagID in (...) --taglist
GROUP BY entityID
HAVING COUNT(DISTINCT tagID) = ... --tagcount

Теперь уловка в том, чтобы заставить Linq произвести его ... Вот некоторый код LinqToSql:

public List<int> GetEntityIds(List<int> tagIds)
{
  int tagCount = tagIds.Count;

  CustomDataContext myDC = new CustomDataContext();

  List<int> entityIds = myDC.Tags
    .Where(t => tagIds.Contains(t.TagId))
    .GroupBy(t => t.entityId)
    .Where(g => g.Select(t => t.TagId).Distinct().Count() == tagCount)
    .Select(g => g.Key)

  return entityIds;
}

Применяются несколько предостережений:

  • List (T) .Contains переводится LinqToSql, но LinqToEntities его не переводит. Вместо этого вы получите исключение во время выполнения.
  • IList.Contains ... никто не переводит это. Вместо этого используйте список (T).
  • Для сервера sql действует ограничение на количество параметров. Это примерно 2000 параметров (выше, но ниже 2500). Если вам нужно использовать более 2000 тегов, вам следует искать другое решение.
  • Я написал это без инструментов, после полуночи. Это, вероятно, не идеально.
0 голосов
/ 22 января 2009

Не уверен, что я действительно понимаю, о чем вы спрашиваете, но, возможно, что-то вроде следующего сработает.

List<string> searchTags = ...

var query = db.MyEntity
              .Where( e => e.Tags.Intersect( searchTags ).Count() > 0 );

Это должно дать вам набор сущностей, где список тегов содержит хотя бы один из элементов в searchTags

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...