Нахождение перекрывающихся интересов в LINQ - PullRequest
6 голосов
/ 17 июня 2011

У меня есть модель, где у места есть некоторые описания, эти описания связаны с интересами (place.description.interests).Пользователь, рассматривающий представление для места, представлен в модели как пользователь, у которого также есть ряд интересов.

Я хочу отсортировать описание по перекрывающимся интересам (включая нулевое перекрытие),где мой текущий Linq:

place dest = (from p in _db.places
                          where p.short_name == id
                          select p).Single();

 return View(dest);

Теперь следующее будет делать то, что я хочу в SQL для рассматриваемой схемы:

SELECT COUNT(interest_user.user_id) AS matches, description.*
FROM description JOIN interest_description ON description.user_id = interest_description.user_id AND description.place_id = interest_description.place_id
    JOIN interest ON interest_description.interest_id = interest.interest_id
    LEFT JOIN interest_user ON interest.interest_id = interest_user.interest_id 
WHERE interest_user.user_id = 2
    AND description.place_id = 1
GROUP BY interest_description.user_id, interest_description.place_id
ORDER BY matches DESC

Но я слишком новичок в Linq, чтобы знатькак бы я справился с этим правильно.В идеале я мог бы справиться с этим, все еще передавая строго типизированную модель.

До сих пор мне это удавалось:

var desc = from d in _db.descriptions
                       from i in d.interests
                       from u in i.users.DefaultIfEmpty()
                       where d.place_id == PlaceID
                           && (u.user_id == userID

(PlaceID и UserID - это аргументы, передаваемые контроллеру, который управляетэто).

Проще говоря, учитывая это linq, мне просто нужно вернуть d, упорядоченный по количеству i.

моя модель enter image description here

Ответы [ 2 ]

3 голосов
/ 20 июня 2011

когда ваш запрос linq становится слишком сложным, я предлагаю вам создать представления в вашей базе данных и поместить их в dbml дизайнер. Я сталкивался с несколькими ситуациями, когда выполнение большого количества группировок в запросах linq приводило к неэффективному sql. Использование представлений не только приведет к прямым запросам linq, но также и к SQL, который вы хотите.

3 голосов
/ 17 июня 2011
place current_place =
    _db.places
    .Include("descriptions.interests.users")
    .Where(p => p.place_id == place_id)
    .First();

var interesting_descriptions =
    from description1 in current_place.descriptions
    select new {
        description = description1,
        matches = (
            from interest1 in description1.interests
            from user1 in interest1.users
            where user1.user_id = user_id
            select 1
        ).Count()
    } into result
    orderby result.matches descending
    select result;

Это примерно эквивалентно SQL

SELECT
    description.*,
    (
        SELECT COUNT(*)
        FROM interest_description
        INNER JOIN interest_user
            ON interest_user.interest_id = interest_description.interest_id
        WHERE interest_description.place_id = description.place_id
        AND interest_description.user_id = description.user_id
        AND interest_user.user_id = @user_id
    ) AS matches
FROM description
WHERE place_id = @place_id
ORDER BY matches DESC

Для каждого описания, связанного с данным местом, оно подсчитывает, сколько раз данный пользователь встречался с любым связанным интересом.

Это даст matches = 0 для описаний, которые не имеют общих интересов с пользователем.

Поскольку GROUP BY / group ... by ... into трудно справиться с пустыми наборами с условиями, этонеобходимо использовать внутренний запрос.

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