2012-01-10 3 views
0

Это мой первый вопрос на любом из этих сайтов, так что простите мой непрофессионализм.Playframework Siena Фильтрация и заказ

Я использую playframework с SIENA модуля (с GAE), и я наткнулся на следующую проблему: давалось 3 лиц:

public class Meeting extends Model{ 

    @Id 
    public Long id; 

    public String place; 

    @Owned 
    Many<MeetingUser> users; 
    . 
    . 
    . 

} 

public class User extends Model{ 

    @Id 
    public Long id; 

    public String firstName; 
    public String lastName; 

    @Owned 
    Many<MeetingUser> meetings; 
    . 
    . 
    . 

} 

public class MeetingUser extends Model{ 

    @Id 
    public Long id; 

    public Meeting meeting; 
    public User user; 
    . 
    . 
    . 
    public User getUser(){ 
     return Model.all(User.class).filter("id", user).get(); 
    } 

    public Meeting getMeeting(){ 
     return Model.all(Meeting.class).filter("id", meeting).get(); 
    } 

} 

Например я перечислю встречу и все их пользователи:

public static void meetingInfo(Long meetingId){ 
    Meeting meeting = Models.all(Meeting.class).filter("id",meetingId); 
    List<MeetingUser> meetingusers = meeting.asList(); 
    List<User> users = new ArrayList<User>(); 
    for(MeetingUser mu: meetingusers){ 
     users.add(mu.getUser()); 
    } 
    render(users); 
} 

Это сделано (есть ли лучший способ здесь?) Однако, когда дело доходит до фильтрации (особенно для динамической фильтрации для многих многих полей), я не могу использовать метод фильтра Query на MeetingUser как Мне нужно отфильтровать поле поля MeetingUser (firstName). Такая же проблема возникает для упорядочения. Мне нужно решение для обеих проблем.

Надеюсь, моя проблема ясна, и я ценю любую помощь здесь.

ответ

0

Помните, что вы находитесь в GAE, который является NoSQL DB. Таким образом, вы не можете выполнить запрос Присоединение, как в СУБД. Тем не менее, на самом деле это не так, потому что это было просто для того, чтобы вы знали об этом;)

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

List<MeetingUser> meetingusers = meeting.users.asQuery().filter("firstname", "XXX"); 

(вы можете также заказать)

тем не менее, зная, что вы не можете присоединиться, помните, что вы не можете написать запрос на поиск встречи, в которых есть пользователи, у которых есть Firstname XXX так как это потребует некоторых объединений, и оно не существует в GAE. В этом случае вам нужно изменить модель следующей NoSQL философии, но это другая тема

рассматривает


Давайте попробуем дать способ сделать то, что вы хотите ...

Ваше отношение это много-ко-многим, что всегда является худшим случаем :)

Вы хотите фильтровать собрание по имени пользователя.
Для этого требуется запрос соединения, который невозможен в GAE. В этом случае вы должны изменить свою модель путем ее денормализации (иногда также использовать избыточность) и управлять соединением самостоятельно. На самом деле, вы должны выполнять работу СУРБД самостоятельно. Это кажется излишним, но на самом деле это довольно легко. Единственным недостатком является то, что вы должны выполнить несколько запросов к БД. NoSQL означает No Schema (& No Join), поэтому есть несколько недостатков, но он позволяет масштабировать и управлять огромной нагрузкой данных ... это зависит от ваших потребностей :)

Выбор, который вы сделали для создания MeetingUser, который является «объединенная» таблица и некая денормализация хороша в GAE, потому что она позволяет управлять соединением самостоятельно.

Решения:

// fetch users by firstname 
List<User> users = users.all().filter("firstName", "John").fetch(); 
// fetch meetingusers associated to these users (verify the "IN" operator works because I didn't use that for a long time and don't remember if it works with this syntax) 
List<MeetingUser> meetingusers = MeetingUser.all().filter("user IN", users); 
// now you must fetch the whole meeting because in MeetingUser, only the Meeting ID is stored (other fields are Null or O) 
List<Meeting> meetings = new ArrayList<Meeting>() 
for(MeetingUsers mu:meetingusers) { 
    meetings.add(meetingusers.meeting); 
} 
// use the batch feature to fetch all objects 
Meeting.batch(Meeting.class).get(meetings); 

// you have your meetings 

Надеется, что это помогает!

+0

Я не знаю, что вы подразумеваете под запросом на соединение. И каково решение для совместимости с GAE. Ваш пример не будет работать в моем опыте, как вы говорите: meeting.users.asQuery() // возвращает запрос .filter ("firstname", "XXX"). Fetch(); // генерирует ошибку, поскольку класс MeetingUser не имеет поля «firstname». –

+0

запрос на соединение - это запрос на несколько таблиц одновременно ... классический SQL JOIN (вы можете найти информацию об этом в сети) – mandubian

+0

Что касается моего примера, я думал, что вы хотите отфильтровать первое имя MeetingUsers ... So кажется, я не понимал, что вы хотели ... – mandubian