MongoDB 连接两个集合

0 mongodb spring-mongo aggregation-framework spring-mongodb

这是订单实体:

public class Order 
{
    @Id
    private String id;
    private String internalId;
    private String externalId;
    private String status;
}

public class OrderAssigned 
{
    @Id
    private String id;
    private String internalId;
    private String externalId;
    private String stationId;
    private String rejectStatus;
}
Run Code Online (Sandbox Code Playgroud)

我想加入这两个集合。

  • 首先我想找到stationId
  • 然后加入Orders.internalIdOrderAssigned.internalIdstatus = "OrderCreated"

就像这个 SQL 查询:

select orders.* 
from PARTNER_RESTAURANT_ORDER orders 
inner join PARTNER_RESTAURANT_ORDER_ASSIGNED_STATION assigned_station on orders.internalId = assigned_station.internalId 
where assigned_station.stationId = "5e2968e2763e750001c8ba5f" 
  and orders.status = "OrderCreated"
Run Code Online (Sandbox Code Playgroud)

Zie*_*zyk 5

MongoDB 并不是最适合连接的,但可以通过$lookup实现。

假设您有以下一组数据:

ORDERS:
{
    _id: 'id-1',
    internalId: 'internal-id-1',
    externalId: 'external-id-1',
    status: 'OrderCreated'
}
{
    _id: 'id-2',
    internalId: 'internal-id-2',
    externalId: 'external-id-2',
    status: 'INACTIVE'
)

ORDERS ASSIGNED:
{
    _id: 'id-1',
    internalId: 'internal-id-1',
    externalId: 'external-id-1',
    stationId: 'station-id-1',
    rejectStatus: 'NONE'
}
{
    _id: 'id-2',
    internalId: 'internal-id-2',
    externalId: 'external-id-2',
    stationId: 'station-id-2',
    rejectStatus: 'NONE'
}
Run Code Online (Sandbox Code Playgroud)

然后:

db.orderAssigned.aggregate([
 {$match: {stationId: {$in: ['station-id-1', 'station-id-2']}}},
 {$lookup: {from: 'order', localField: 'internalId', foreignField: 'internalId', as: 'orders'}}
])
Run Code Online (Sandbox Code Playgroud)

会给你:

{
    "_id" : "id-1",
    "internalId" : "internal-id-1",
    "externalId" : "external-id-1",
    "stationId" : "station-id-1",
    "rejectStatus" : "NONE",
    "orders" : [
        {
            "_id" : "id-1",
            "internalId" : "internal-id-1",
            "externalId" : "external-id-1",
            "status" : "OrderCreated"
        }
    ]
}
{
    "_id" : "id-2",
    "internalId" : "internal-id-2",
    "externalId" : "external-id-2",
    "stationId" : "station-id-2",
    "rejectStatus" : "NONE",
    "orders" : [
        {
            "_id" : "id-2",
            "internalId" : "internal-id-2",
            "externalId" : "external-id-2",
            "status" : "INACTIVE"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您需要一些额外的连接条件,那么status = "OrderCreated"更适合您的是带有管道的$lookup的第二个版本:

db.orderAssigned.aggregate([
 {$match: {stationId: {$in: ['station-id-1', 'station-id-2']}}},
 {$lookup: 
    {
        from: 'order', 
        let: {joinValue: '$internalId'}, 
        pipeline: [
            { $match:
                 { $expr:
                    { $and:
                       [
                         { $eq: [ "$internalId",  "$$joinValue" ] },
                         { $eq: [ "$status", "OrderCreated" ] }
                       ]
                    }
                 }
                  }     
        ], 
        as: 'orders'}}
])

Run Code Online (Sandbox Code Playgroud)

会给你:

{
    "_id" : "id-1",
    "internalId" : "internal-id-1",
    "externalId" : "external-id-1",
    "stationId" : "station-id-1",
    "rejectStatus" : "NONE",
    "orders" : [
        {
            "_id" : "id-1",
            "internalId" : "internal-id-1",
            "externalId" : "external-id-1",
            "status" : "OrderCreated"
        }
    ]
}
{
    "_id" : "id-2",
    "internalId" : "internal-id-2",
    "externalId" : "external-id-2",
    "stationId" : "station-id-2",
    "rejectStatus" : "NONE",
    "orders" : [ ]
}
Run Code Online (Sandbox Code Playgroud)