SpringData mongoDB API для агрегации $map

Ниже приведен мой собственный запрос MongoDB, а ниже приведен эквивалент SpringData Mongo API. Меня поражает использование $map в $project в SpringData Mongo API. Благодарю вас за помощь в завершении моего перехода на API

db.users.aggregate([    
    { $match: {$and : [{userType:"200"} },    
     { $unwind: "$userOrgMap" },
    {
      $lookup:
        {
          from: "users",
          localField: "userOrgMap.createdbyuser",
          foreignField: "_id",
          as: "created_by"
        }
   },
   {$project:{
       _id:"$_id",
       login:"$login",
       firstName:"$firstName",
       lastName:"$lastName",
       email:"$email",
       deactivateFlag:"$deactivateFlag",
       createdOn:"$createdOn",
       createdBy:{
        "$map": { 
                    "input": "$created_by", 
                    "as": "u", 
                      "in": { 
                          "name": { "$concat" : [ "$$u.firstName", " ", "$$u.lastName" ] }, 
                      } 
                }
    }
      }
    },
    { $sort : { createdBy : 1} }

])

Весенний запрос

 Aggregation aggregation = newAggregation(
            Aggregation.match(Criteria.where("userType").is(userType)),
            Aggregation.unwind("userOrgMap"),
            Aggregation.lookup("users", "userOrgMap.createdbyuser", "_id", "created_by"),
            Aggregation.project("userId","login","firstName","lastName","email","deactivateFlag","createdOn")
        );

person karmaker    schedule 13.05.2017    source источник
comment
comment
Спасибо за информацию. Но мне нужна дополнительная помощь, чтобы разобраться с API. Мое требование другое. Aggregation.project(userId,login,firstName,lastName,email,deactivateFlag,createdOn) .and(mapItemsOf(created_by).as(u). ??? )).as(createdBy)   -  person karmaker    schedule 13.05.2017


Ответы (2)


Вы можете попробовать ниже $map агрегацию.

  project().and(mapItemsOf("created_by").
                            as("u").
                            andApply(new AggregationExpression() {
                                @Override
                                public DBObject toDbObject(AggregationOperationContext aggregationOperationContext) {
                                    return new BasicDBObject("name", StringOperators.valueOf("u.firstName").concat(" ").concatValueOf("u.lastName").toDbObject(aggregationOperationContext));
                                }
                            }))
             .as("createdBy");

Использование выражения $let

 project().and(VariableOperators.Let.define(VariableOperators.Let.ExpressionVariable.newVariable("u").forExpression(ArrayOperators.arrayOf("created_by").elementAt(0))).
                            andApply(new AggregationExpression() {
                                @Override
                                public DBObject toDbObject(AggregationOperationContext aggregationOperationContext) {
                                    return new BasicDBObject("name", StringOperators.valueOf("u.firstName").concat(" ").concatValueOf("u.lastName").toDbObject(aggregationOperationContext));
                                }
                            }))
            .as("createdBy");

Используйте лямбда и статический импорт.

import static org.springframework.data.mongodb.core.aggregation.ArrayOperators.arrayOf;
import static org.springframework.data.mongodb.core.aggregation.StringOperators.valueOf;
import static org.springframework.data.mongodb.core.aggregation.VariableOperators.Let.ExpressionVariable.*;
import static org.springframework.data.mongodb.core.aggregation.VariableOperators.Let.define;
import static org.springframework.data.mongodb.core.aggregation.VariableOperators.mapItemsOf;

project().and(mapItemsOf("created_by").
                as("u").
                andApply(aggregationOperationContext -> new BasicDBObject("name", valueOf("u.firstName").concat(" ").concatValueOf("u.lastName").toDbObject(aggregationOperationContext))))
                .as("createdBy");

    project().and(define(newVariable("u").forExpression(arrayOf("created_by").elementAt(0))).
            andApply(aggregationOperationContext -> new BasicDBObject("name", valueOf("u.firstName").concat(" ").concatValueOf("u.lastName").toDbObject(aggregationOperationContext))))
            .as("createdBy");
person s7vr    schedule 13.05.2017
comment
Ценю ваш быстрый ответ. Но я получаю неопределенный - person karmaker; 13.05.2017
comment
Нп. Обновлен ответ, чтобы включить псевдоним name для использования карты. Я не вижу ничего в API, чтобы указать псевдоним во вложенном выражении. Поэтому я использовал BasicDBObject для создания выражения. Вы также можете сделать это с оператором $let, используя $arrayElemAt и $concat. - person s7vr; 13.05.2017
comment
Просто понял, что результат не тот, что создан. Я получаю следующее: [ \Chithra Nattamai Subburaman\]}] Я ожидаю, что будет создано следующее: [ { name : kaushik Mehta } ] - person karmaker; 15.05.2017
comment
Вы имеете в виду, что отсутствует поле name? с выхода? Да, я упомянул об этом во втором комментарии. Пожалуйста, используйте последний код. Это будет работать. - person s7vr; 15.05.2017
comment
Мое требование состоит в том, чтобы создать createBy в качестве дополнительного поля с конкатом firstName и lastName. Я слышал об использовании addField в агрегации. Но не уверен, как использовать его для достижения. Если создание createdBy невозможно без массива, я в порядке. Но я не хочу [\ из вывода. Потому что на выходе я получаю [ как строковое значение, а не как массив. Я бы предпочел получить тот же результат, что и для собственного запроса. Пожалуйста, помогите - person karmaker; 15.05.2017
comment
Это дополнительное поле. Мой проект не включает другие поля для ясности. Вывод вашего собственного запроса также содержит массив. Если вам не нужен массив, используйте второе решение, которое использует оператор $let для возврата документа. - person s7vr; 15.05.2017
comment
После использования $let результатом будет createdBy:{ \name\ : \Kaushik Mehta\}. Можно ли получить создано:Kaushik Mehta. Если это невозможно, я могу сортировать по createdBy.name вместо createdBy. Кроме того, возможно ли получить значение без \. - person karmaker; 15.05.2017
comment
Попробуйте project().and(define(newVariable("u").forExpression(arrayOf("created_by").elementAt(0))).andApply(valueOf("u.firstName").concat(" ").concatValueOf("u.lastName"))).as("created_by") - person s7vr; 15.05.2017
comment
.and(VariableOperators.define(ExpressionVariable.newVariable(temp) .forExpression(ArrayOperators.arrayOf(created_by).elementAt(0))) .andApply(va‌​lueOf(temp.firstName)‌​.concat().concatValueOf(temp .фамилия))) .as(создано), - person karmaker; 16.05.2017
comment
Я прав в использовании? Также valueOf выдает ошибку компиляции. - person karmaker; 16.05.2017
comment
Попробуйте включить статический импорт из ответа. Define должен быть частью операторов let переменных - person s7vr; 16.05.2017
comment
.and(VariableOperators.define(ExpressionVariable.newVariable(temp) .forExpression(ArrayOperators.arrayOf(created_by).elementAt(0))) .andApply(StringOperators.valueOf(temp.firstName) .concat( ).concatValueOf(temp.lastName ))) .as(создано) - person karmaker; 16.05.2017
comment
импортировать org.springframework.data.mongodb.core.aggregation.VariableOperators; импортировать org.springframework.data.mongodb.core.aggregation.ArrayOperators; импортировать org.springframework.data.mongodb.core.aggregation.VariableOperators.Let.ExpressionVariable; - person karmaker; 16.05.2017
comment
Я имел в виду это import static org.springframework.data.mongodb.core.aggregation.VariableOperators.Let.define; - person s7vr; 16.05.2017

Это еще один подход, который я смог сделать.

Aggregation.project("userId","login","firstName","lastName","email","deactivateFlag","createdOn").and(VariableOperators.Map.itemsOf("created_by").as("u").andApply(StringOperators.Concat.valueOf("$$u.firstName").concat(" ").concatValueOf("$$u.lastName"))).as("createdBy");
person Divya Gopal    schedule 31.12.2019