Как сравнить две коллекции и архивные документы, которые не являются общими - PullRequest
0 голосов
/ 19 марта 2019

У меня есть две коллекции, например, CollectionA и CollectionB, обе имеют общее поле, которое называется hostname

Коллекция А:

    {

  "hostname": "vm01",
  "id": "1",
  "status": "online",

}

Коллекция B

{

  "hostname": "vm01",
  "id": "string",
  "installedversion": "string",

}

{

  "hostname": "vm02",
  "id": "string",
  "installedversion": "string",

}

что я хочу достичь, это когда я получаю сообщение для коллекции B

  • Я хочу проверить, существует ли запись в Коллекции B на основе имени хоста, и обновить все значения. если не вставить новую запись (я читал, что это может быть достигнуто с помощью upsert - все еще ищу, как заставить его работать)

    • Я хочу проверить, присутствует ли имя хоста в коллекции A, если нет, переместить запись из коллекции B в другую коллекцию, которая является коллекцией C (как архивные записи). То есть в приведенном выше описании hostname = vm02 запись из коллекции B должна быть перемещено в коллекцию C

Как я могу добиться этого с помощью Springboot Mongodb. Любая помощь приветствуется. Код, который я должен сохранить для коллекции B, выглядит следующим образом, и я хочу обновить его для достижения желаемого результата, указанного выше

public RscInstalltionStatusDTO save(RscInstalltionStatusDTO rscInstalltionStatusDTO) {
    log.debug("Request to save RscInstalltionStatus : {}", rscInstalltionStatusDTO);

    RscInstalltionStatus rscInstalltionStatus = rscInstalltionStatusMapper.toEntity(rscInstalltionStatusDTO);
    rscInstalltionStatus = rscInstalltionStatusRepository.save(rscInstalltionStatus);
    return rscInstalltionStatusMapper.toDto(rscInstalltionStatus);
}

Обновление 1: Ниже работает, как я ожидал, но я думаю, что должен быть лучший способ сделать это.

   public RscInstalltionStatusDTO save(RscInstalltionStatusDTO rscInstalltionStatusDTO) {
        log.debug("Request to save RscInstalltionStatus : {}", rscInstalltionStatusDTO);


        RscInstalltionStatus rscInstalltionStatus = rscInstalltionStatusMapper.toEntity(rscInstalltionStatusDTO);
        System.out.print(rscInstalltionStatus.getHostname());
        Query query = new Query(Criteria.where("hostname").is(rscInstalltionStatus.getHostname()));
        Update update = new Update();
        update.set("configdownload",rscInstalltionStatus.getConfigdownload());
        update.set("rscpkgdownload",rscInstalltionStatus.getRscpkgdownload());
        update.set("configextraction",rscInstalltionStatus.getConfigextraction());
        update.set("rscpkgextraction",rscInstalltionStatus.getRscpkgextraction());
        update.set("rscstartup",rscInstalltionStatus.getRscstartup());
        update.set("installedversion",rscInstalltionStatus.getInstalledversion());
        mongoTemplate.upsert(query, update,RscInstalltionStatus.class);
        rscInstalltionStatus = rscInstalltionStatusRepository.findByHostname(rscInstalltionStatus.getHostname());
        return rscInstalltionStatusMapper.toDto(rscInstalltionStatus);
    }

Update2: с помощью приведенного ниже кода я могу переместить записи в другую коллекцию

String query = "{$lookup:{ from: \"vmdetails\",let: {rschostname: \"$hostname\"},pipeline:[{$match:{$expr:{$ne :[\"$hostname\",\"$$rschostname\"]}}}],as: \"rscInstall\"}},{$unwind:\"$rscInstall\"},{$project:{\"_id\":0,\"rscInstall\":0}}";
AggregationOperation rscInstalltionStatusTypedAggregation = new CustomProjectAggregationOperation(query);


LookupOperation lookupOperation = LookupOperation.newLookup().from("vmdetails").localField("hostname").foreignField("hostname").as("rscInstall");
UnwindOperation unwindOperation = Aggregation.unwind("$rscInstall");

ProjectionOperation projectionOperation = Aggregation.project("_id","rscInstall").andExclude("_id","rscInstall");
OutOperation outOperation = Aggregation.out("RscInstallArchive");
Aggregation aggregation = Aggregation.newAggregation(rscInstalltionStatusTypedAggregation,unwindOperation,projectionOperation,outOperation);
List<BasicDBObject> results = mongoTemplate.aggregate(aggregation,"rsc_installtion_status",BasicDBObject.class).getMappedResults();

эта проблема, которая у меня есть, возвращает несколько записей

1 Ответ

0 голосов
/ 22 марта 2019

Нашли решение, могут быть и другие лучшие решения, но для меня это сработало

создать класс customeAggregationGeneration (найден в SO-ответах и ​​расширен для соответствия моим потребностям)

public class CustomProjectAggregationOperation implements AggregationOperation {

private String jsonOperation;

public CustomProjectAggregationOperation(String jsonOperation) {
    this.jsonOperation = jsonOperation;
}

@Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
    return aggregationOperationContext.getMappedObject(Document.parse(jsonOperation));
}
}



  String lookupquery = "{$lookup :{from:\"vmdetails\",localField:\"hostname\",foreignField:\"hostname\"as:\"rscinstall\"}}";
        String matchquery = "{ $match: { \"rscinstall\": { $eq: [] } }}";
        String projectquery = "{$project:{\"rscinstall\":0}}";

        AggregationOperation lookupOpertaion = new CustomProjectAggregationOperation(lookupquery);
        AggregationOperation matchOperation = new CustomProjectAggregationOperation(matchquery);
        AggregationOperation projectOperation = new CustomProjectAggregationOperation(projectquery);

        Aggregation aggregation = Aggregation.newAggregation(lookupOpertaion, matchOperation, projectOperation);
        ArrayList<Document> results1 = (ArrayList<Document>) mongoTemplate.aggregate(aggregation, "rsc_installtion_status", Document.class).getRawResults().get("result");

        // System.out.println(results1);

        for (Document doc : results1) {

         //   System.out.print(doc.get("_id").toString());
            mongoTemplate.insert(doc, "RscInstallArchive");
            delete(doc.get("_id").toString());
...