$ lookup с использованием нескольких критериев агрегации mongodb java - PullRequest
0 голосов
/ 20 апреля 2020

Имеют 2 следующие коллекции:

коллекция пользователей

{
userId:user1,
creationTimeStamp:2019-11-05T08:15:30
status:active
},
{
userId:user2,
creationTimeStamp:2019-10-05T08:15:30
status:active
}

коллекция документов

{
userId:user1,
category:Development
published:true
},
{
userId:user2,
category:Development
published:false
}

Я хочу объединить эти две коллекции и отфильтровать пользователей таким образом, чтобы документы, которые относятся к категории разработки и не публикуются у активных пользователей в период времени создания

Как написать агрегацию mongodb java, чтобы получить такой результат:

{
userId: user2,
status:active,
category:Development,
published:false
}

Ответы [ 2 ]

2 голосов
/ 20 апреля 2020

Вы не упомянули о дубликате userId в коллекции User.

Таким образом, скрипт имеет вид

[{
    $match: {
        category: "Development",
        published: false
    }
}, {
    $lookup: {
        from: 'user',
        localField: 'userId',
        foreignField: 'userId',
        as: 'joinUser'
    }
}, {
    $unwind: {
        path: "$joinUser",
        preserveNullAndEmptyArrays: true
    }
}, {
    $match: {
        "joinUser.status": "active"
    }
}, {
    $addFields: {
        "status": "$joinUser.status"
    }
}, {
    $project: {
        _id: 0,
        userId: 1,
        category: 1,
        published: 1,
        status: 1
    }
}]

И код java,

включает этот импорт

import static org.springframework.data.mongodb.core.aggregation.Aggregation.match;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.lookup;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.unwind;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.project;

метод,

public Object findAllwithVideos() {
    Aggregation aggregation=Aggregation.newAggregation(
        match(Criteria.where("category").is("Development").and("published").is(false)),
        lookup("user","userId","userId","joinUser"),
        unwind("joinUser",true),
        new AggregationOperation(){
            @Override
            public Document toDocument(AggregationOperationContext aggregationOperationContext){
                return new Document("$addFields",
                    new Document("status","$joinUser.status")
                );
            }
        },
        project("userId","category","published","status")
    ).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());

    return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(Document.class), Object.class);
}
1 голос
/ 20 апреля 2020

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

[{$match: {
  category:'development',
  published: false
}}, {$lookup: {
  from: 'user',
  localField: 'userId',
  foreignField: 'userId',
  as: 'JoinedTable'
}}, {$unwind: {
  path: '$JoinedTable'

 }}, {$group: {
  _id: '$_id',
  userId: {
    $first: '$userId'
  },
  status: {
    $first: '$JoinedTable.status'
  },
  category: {
    $first: '$category'
  },
  published: {
    $first: '$published'
  },
}}]

enter image description here

Объяснение:

1. filter documents using match for criteria category: 'development' & published: false 
2. join document collection with user collection with key userId
3. unwind the joined collection field to convert array to object
4. project the fields needed using groups.

Hope this helps!
...