当前位置:   article > 正文

SpringDataMongo用于多条件连接的LookupOperation构造工具_spingdata mongo lookup

spingdata mongo lookup

普遍使用的{from, localField, foreignField, as}形式的$lookup只实现了单条件连接表,但是有时候我们会碰到需要多条件连接的情况,其实mongodb3.6版本之后已经支持了这种操作(详情见这里),但是SpringDataMongo的MongoOperation(MongoTemplate)还没有去适配。这里提供了一个简单的工具类

LookupLetPipelinesOperation.java
package vip.starhouse.propertyservicemp.infrastructure.common.db.mongo.custom;

import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
import org.bson.Document;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author 金艺群
 * @description
 * @date 2021/07/28
 **/
public class LookupLetPipelinesOperation implements AggregationOperation {
    private String jsonOperation;
    private String from;
    private String as;
    private List<String> foreignFields;
    private List<String> localFields;

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

    public LookupLetPipelinesOperation() {

    }

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

    public static LookupLetPipelinesOperation LookupLetPipelinesOperation() {
        LookupLetPipelinesOperation v = new LookupLetPipelinesOperation("{$lookup: {\n" +
                "    from: '%s', \n" +
                "    let: {%s}, \n" +
                "    pipeline: [\n" +
                "        {$match: {$expr: {$and: [%s]} }}    \n" +
                "    ], \n" +
                "    as: '%s'}\n" +
                "}\n");
        v.foreignFields = new ArrayList<>();
        v.localFields = new ArrayList<>();
        return v;
    }

    public LookupLetPipelinesOperation from(String from) {
        this.from = from;
        return this;
    }

    public LookupLetPipelinesOperation match(String localField, String foreignField) {
        this.localFields.add(localField);
        this.foreignFields.add(foreignField);
        return this;
    }

    public LookupLetPipelinesOperation as(String as) {
        this.as = as;
        return this;
    }

    public LookupLetPipelinesOperation build() {
        String foreignFieldsIntegral = generateForeignFieldsIntegral();
        String matchPairs = generateMatchPairs();
        this.jsonOperation = String.format(this.jsonOperation, from, foreignFieldsIntegral, matchPairs, as);
        return this;
    }

    private String generateForeignFieldsIntegral() {
        StringBuilder sb = new StringBuilder();
        this.foreignFields.forEach(f -> {
            sb.append(f);
            sb.append(":");
            sb.append("'$");
            sb.append(f);
            sb.append("'");
            sb.append(",");
        });
        return sb.deleteCharAt(sb.length() - 1).toString();
    }

    private String generateMatchPairs() {
        StringBuilder sb = new StringBuilder();
        Iterator<String> localIte = this.localFields.iterator();
        Iterator<String> foreignIte = this.foreignFields.iterator();
        while (localIte.hasNext()) {
            String l = localIte.next();
            String f = foreignIte.next();
            sb.append("{$eq: ['$");
            sb.append(l);
            sb.append("',");
            sb.append("'$$");
            sb.append(f);
            sb.append("']}");
            sb.append(",");
        }
        return sb.deleteCharAt(sb.length() - 1).toString();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
使用

LookupLetPipelinesOperation letPipelineLookup = LookupLetPipelinesOperation.LookupLetPipelinesOperation()
                .from("message")
                .match("from", "from")
                .match("to", "to")
                .as("ms")
                .build();
        FacetOperation facets = Aggregation.facet()
               (..........);
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(Criteria.where("_id").is(new ObjectId(messageId))),
                Aggregation.limit(1),
                // 获取 MessageId对应的from&to,根据这两个id进行多条件连接
                // 多条件连接
                letPipelineLookup,
                Aggregation.unwind("ms"),
                Aggregation.project()
                        .and("ms._id").as("_id")
                        .and("ms.from").as("from")
                        .and("ms.to").as("to")
                        .and("ms.content").as("content")
                        .and("ms.property_id").as("property_id")
                        .and("ms.created_at").as("created_at")
                        .and("ms.updated_at").as("updated_at"),
                facets,
                Aggregation.unwind("introduction"),
                Aggregation.addFields().addField("introduction").withValue("$introduction.share_title").build()
        );
        List<MessageListVO> resultList = mongo.aggregate(aggregation, "message", MessageListVO.class).getMappedResults();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/56032
推荐阅读
相关标签
  

闽ICP备14008679号