2014-11-26 3 views
3

у меня есть такие поля в сущности:MongoDB Агрегация. Проверьте, если вложенный массив содержит значение

private String userId; 
private String username; 
private Date created; 
private List<Comment> comments = new ArrayList<>(); 

Comment есть такие поля:

private String userId; 
private String username; 
private String message; 
private Date created; 

мне нужно сделать агрегацию, и получить что-то вроде этого:

{ 
    "userId" : "%some_userId%", 
    "date" : "%some_date%", 
    "commentsQty" : 100, 
    "isCommented" : true 
} 

Мое агрегирование выглядит следующим образом:

{ "aggregate" : "%entityName%" , "pipeline" : [ 
    { "$project" : { 
       "username" : 1 , 
       "userId" : 1 , 
       "created" : 1 , 
       "commentQty" : { "$size" : [ "$comments"]}}}]} 

И он отлично работает. Но мне нужно также проверить, что IF comments array содержит некоторый комментарий, с определенным userId. Я попробовал это одно, но оно не исполняет:

{ "aggregate" : "%entityName%" , "pipeline" : [ 
    { "$project" : { 
       "username" : 1 , 
       "userId" : 1 , 
       "created" : 1 , 
       "commentQty" : { "$size" : [ "$comments"]} , 
       "isCommented" : { "$exists" : [ "$comments.userId" , "5475b1e45409e07b0da09235"]}}}]} 

с таким сообщением: Command execution failed: Error [exception: invalid operator '$exists']

Как такая проверка может быть сделано?

UPD: Также судимые операторы $in и подобные, но они действительны для беспокойства, а не для агрегации.

ответ

3

с таким сообщением: выполнение команды не удалось: Error [исключение: неверный оператор '$ существует']

В настоящее время оператор $exists не доступен в aggregation трубопровода.

редактировать:

написание лучшего ответа:

Вы можете проверить, если какой-либо пользователь комментирует, автор:

  • с помощью $setIntersection оператора, чтобы получить массив с userId мы ищут, если пользователь действительно прокомментировал сообщение.
  • примените оператор $size, чтобы получить размер результирующего массива.
  • использовать $gt оператора, если размер превышает 0.
  • если есть, значит, один или несколько комментариев от userId мы ищем, иначе нет.

Пример кода:

var userIdToQuery = "2"; 
var userIdsToMatchAgainstComments = [ObjectId("5475b1e45409e07b0da09235")]; 

db.t.aggregate([ 
{$match:{"userId":userIdToQuery}}, 
{$project:{"userName":1, 
      "created":1, 
      "commentQty":{$size:"$comments"}, 
      "isCommented":{$cond: 
          [{$gt:[ 
          {$size: 
          {$setIntersection:["$comments.userId", 
            userIdsToMatchAgainstComments]}} 
          ,0]}, 
          true,false]}}} 
]) 

предыдущий ответ:

  • Unwind комментарии.
  • Project дополнительное поле isCommented Для каждого документа комментариев, проверить, если он имеет userId, что мы ищем, если он имеет соответствующий userId, затем установите переменную 1 еще 0.
  • Group вместе документы снова, просуммировать значения в isCommented, если это > 0, документ с идентификатором пользователя присутствует в группе еще не .
  • Project полей соответственно.

Кодекс:

{ "aggregate" : "%entityName%" , "pipeline" :[ 
    {$unwind:"$comments"}, 
    {$project:{ 
       "username":1, 
       "userId":1, 
       "created":1, 
       "comments":1, 
       "isCommented":{$cond:[{$eq:["$comments.userId", 
              ObjectId("5475b1e45409e07b0da09235") 
              ] 
            }, 
            1, 
            0]}}}, 
    {$group:{"_id":{"_id":"$_id", 
        "username":"$username", 
        "userId":"$userId", 
        "created":"$created"}, 
      "isCommented":{$sum:"$isCommented"}, 
      "commentsArr":{$push:"$comments"}}}, 
    {$project:{"comments":"$commentsArr", 
       "_id":0, 
       "username":"$_id.username", 
       "userId":"$_id.userId", 
       "created":"$_id.userId", 
       "isCommented":{$cond:[{$eq:["$isCommented",0]}, 
            false, 
            true]}, 
       "commentQty":{$size:"$commentsArr"}}}, 
    ]} 
+0

Спасибо за ответ. Но кажется, что это не то, что мне нужно. Мне нужно проверить, имеет ли массив CONTAINS определенное значение. В моем случае мне нужно проверить, если массив $ comments содержит комментарий с userId, скажем, «5475b1e45409e07b0da09235». – Shatranaft

+0

Я имею в виду, isCommented поле, это - комментирует ME, средний, текущий пользователь. Поэтому мне нужно проверить его во время агрегации, чтобы избежать еще одного запроса mongo ... – Shatranaft

+0

Проверьте мой обновленный ответ. Итак, у комментариев - userId будет ObjectId соответствующего пользователя? – BatScream

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