2016-07-07 1 views
0

Мне нужна помощь/совет о том, как реплицировать поведение SQL в MongoDB. В частности, учитывая эту коллекцию:Aggregation MongoDb (стиль SQL UNION)

{ 
    "_id" : ObjectId("577ebc0660084921141a7857"), 
    "tournament" : "Wimbledon", 
    "player1" : "Agassi", 
    "player2" : "Lendl", 
    "sets" : [{ 
     "score1" : 6, 
     "score2" : 4, 
     "tiebreak" : false 
    }, { 
     "score1" : 7, 
     "score2" : 6, 
     "tiebreak" : true 
    }, { 
     "score1" : 7, 
     "score2" : 6, 
     "tiebreak" : true 
    }] 
} 
{ 
    "_id" : ObjectId("577ebc3560084921141a7858"), 
    "tournament" : "Wimbledon", 
    "player1" : "Ivanisevic", 
    "player2" : "McEnroe", 
    "sets" : [{ 
     "score1" : 4, 
     "score2" : 6, 
     "tiebreak" : false 
    }, { 
     "score1" : 3, 
     "score2" : 6, 
     "tiebreak" : false 
    }, { 
     "score1" : 6, 
     "score2" : 4, 
     "tiebreak" : false 
    }] 
} 
{ 
    "_id" : ObjectId("577ebc7560084921141a7859"), 
    "tournament" : "Roland Garros", 
    "player1" : "Navratilova", 
    "player2" : "Graf", 
    "sets" : [{ 
     "score1" : 5, 
     "score2" : 7, 
     "tiebreak" : false 
    }, { 
     "score1" : 6, 
     "score2" : 3, 
     "tiebreak" : false 
    }, { 
     "score1" : 7, 
     "score2" : 7, 
     "tiebreak" : true 
    }, { 
     "score1" : 7, 
     "score2" : 5, 
     "tiebreak" : false 
    }] 
} 

И эти два разных скоплений:

1) агрегация ALFA: это агрегация нарочно странно, в том смысле, что он предназначен, чтобы найти все матчи, где по крайней мере 1 тай-брейк верен, но только показывает наборы, где тай-брейк ложный. Пожалуйста, не учитывайте его логику, она создана для обеспечения полной свободы для пользователя.

{ 
    $match: { 
     "tournament": "Wimbledon", 
     "sets.tiebreak": true 
    } 
}, 
{ 
    $project: { 
     "tournament": 1, 
     "player1": 1, 
     "sets": { 
      $filter: { 
       input: "$sets", 
       as: "set", 
       cond: { 
        $eq: ["$$set.tiebreak", false] 
       } 
      } 
     } 
    } 
} 

2) агрегация BETA: это агрегация нарочно странно, в том смысле, что он предназначен, чтобы найти все матчи, где по крайней мере, один тай-брейк является ложным но только показывает наборы, где тай-брейк верно , Пожалуйста, не учитывайте его логику, она создана для обеспечения полной свободы для пользователя. Обратите внимание, что player1 скрыт от результатов.

{ 
    $match: { 
     "tournament": "Roland Garros", 
     "sets.tiebreak": false 
    } 
}, 
{ 
    $project: { 
     "tournament": 1, 
     "sets": { 
      $filter: { 
       input: "$sets", 
       as: "set", 
       cond: { 
        $eq: ["$$set.tiebreak", true] 
       } 
      } 
     } 
    } 
} 

Теперь предположим, что эти два скопления цель состоит в том, чтобы разграничить то, что часть базы данных пользователь может видеть, в том смысле, что эти два запроса разграничить все документы (и детали), которые видны пользователю. Это похоже на 2 sql-представления, которые пользователь имеет права доступа.

Мне нужно/нужно попытаться переписать предыдущие отдельные агрегаты только в одном. Может ли это быть достигнуто?

Оно является обязательным, чтобы сохранить все ограничения, которые были установлены в Aggregation A & B, без потери какого-либо контроля над данными и без утечки, и данные, которые не были доступны в запросе А или Б.

В частности, матчи в Уимблдон можно увидеть только в том случае, если у них есть хотя бы один сет, который закончился тай-брейком. Поле Player1 МОЖЕТ быть видимым. Отдельные наборы должны быть скрыты, если они не заканчиваются тай-брейком и скрыты в противном случае. При необходимости приемлемо, но нежелательно, чтобы вообще не видеть плеер1.

И наоборот, спички в Roland Garros можно увидеть только в том случае, если они имели хотя бы один комплект, который закончился без перерыва. Поле Player1 ДОЛЖНО быть скрытым. Отдельные наборы должны быть видны, если они заканчиваются тай-брейком и скрыты в противном случае.

Опять же, цель состоит в объединении двух агрегатов, сохраняя ограничения, налагаемые двумя агрегатами.

MongoDB - версия 3.5, при необходимости может быть обновлена ​​до неустойчивых выпусков.

+0

было бы лишним использовать регулярные выражения в текстовых фильтрах. Стратегии, ориентированные на достижение конкретных результатов, являются плюсом, но не обязательными. – Manuele

+0

Мне кажется, что вы извлекаете данные из одной коллекции, чтобы получить оба типа данных try $ или. UNION обычно тянет из разных таблиц с похожими столбцами. – Tiramisu

+0

Да, я вытаскиваю из одной коллекции ... но, к сожалению, дело не в стадии $ match (используя $ или ...), а в стадии $ project, которая кажется невозможной/слишком сложной для меня ... Спасибо в любом случае! – Manuele

ответ

0

вот мои два цента за вопрос:
, если вы хотите, чтобы избежать пустых наборов при

  • к документу "Уимблдон" имеет всеtrue tibreaks,
  • или "Roland Garros "имеет всеfalse tiebreaks

вы можете изменить запрос:

... 
{ 
    $and: [{ 
    "sets.tiebreak": true, 
    }, { 
    "sets.tiebreak": false 
    }], 
    $or: [{ 
    "tournament": "Wimbledon" 
    }, { 
    "tournament": "Roland Garros" 
    }] 
} 
... 

и использовать его в:

+0

Трудно сказать, какой из них правильный, поскольку это был просто тест. Суть этого заключалась в том, чтобы имитировать SQL UNION. Поскольку «Агрегирование ALFA/BETA» возвращает пустые множества, я думаю, что мой запрос по-прежнему является самым правильным, но ваша заметка указывает на более чем правильную аннотацию. Было бы неплохо сравнить два разных подхода. Я думаю, что больше этапов = больше времени, но также может быть, что проекция * hard * может потреблять еще больше времени, чем список совпадений/разматываний/совпадений ... Будет ли расследоваться ... – Manuele

+0

Я не буду отмечать ваш ответ как исправьте его по причинам предыдущего комментария, но это, безусловно, действительный подход. – Manuele

 Смежные вопросы

  • Нет связанных вопросов^_^