如何从两个不同集合中的对象数组访问字段?

时间:2017-10-25 10:30:01

标签: mongodb

这是locations集合数据。

{
  _id: "1",
  location: "loc1",
  sublocations: [
    {
      _id: 2,
      sublocation: "subloc1",
    },
    {
      _id: 3,
      sublocation: "subloc2",
    }
  ]
},
{
  _id: "4",
  location: "loc2",
  sublocations: [
    {
      _id: 5,
      sublocation: "subloc1",
    },
    {
      _id: 6,
      sublocation: "subloc2",
    }
  ]
}

这是products集合数据

{
  _id: "1",
  product: "product1",
  prices: [
    {
      _id: 2,
      sublocationid: 2,        //ObjectId of object in sublocations array 
      price: 500
    },
    {
      _id: 3,
      sublocationid: 5,        //ObjectId of object in sublocations array
      price: 200
    }
  ]
}

现在我需要在价格数组中获取产品架构中的sublocation。预期结果如下。

{
  _id: "1",
  product: "product1",
  prices: [
    {
      _id: 2,
      sublocationid: 3,
      sublocation: "subloc2", 
      price: 500
    },
    {
      _id: 3,
      sublocationid: 5,
      sublocation: "subloc1"
      price: 200
    }
  ]
}

为了实现它,我按照以下方式做到了。

  • 首先,在locations集合上执行聚合 - $展开sublocations数组并将$ out存储在新集合中。
  • 其次,对'产品'集合执行聚合 - $展开价格,$从新集合中查找sublocationid并将它们分组。
  • 第三,在获取数据后删除新集合的数据。

还有其他简化方法吗?如果有的话请告诉我。

2 个答案:

答案 0 :(得分:1)

您可以在3.6版本中尝试以下聚合查询。

由于本地字段和外部字段都是数组,因此您必须$unwind进行相等比较。

为此,您必须使用新的$lookup语法。

带有$match

$expr提供了文档字段之间的比较,以便为每个产品的子位置ID查找位置的子位置文档。

$project投影匹配的子位置文档。

带有$addFields

$arrayElemAt将查找到的子位置数组转换为文档。

$group以每个产品的匹配子位置文档推送所有价格。

db.products.aggregate[
  {
    "$unwind": "$prices"
  },
  {
    "$lookup": {
      "from": "locations",
      "let": {
        "prices": "$prices"
      },
      "pipeline": [
        {
          "$unwind": "$sublocations"
        },
        {
          "$match": {
            "$expr": [
              "$$prices.sublocationid",
              "$sublocations._id"
            ]
          }
        },
        {
          "$project": {
            "sublocations": 1,
            "_id": 0
          }
        }
      ],
      "as": "prices.sublocations"
    }
  },
  {
    "$addFields": {
      "prices.sublocations": {
        "$arrayElemAt": [
          "$prices.sublocations",
          0
        ]
      }
    }
  },
  {
    "$group": {
      "_id": "$_id",
      "product": {
        "$first": "$product"
      },
      "prices": {
        "$push": "$prices"
      }
    }
  }
])

答案 1 :(得分:1)

如果您想坚持使用3.4版本,可以尝试以下查询:

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (!socketClosed) {
    String incomingMessage = in.readLine();
    if (incomingMessage != null) {
        incomingMessagesHandler.handleMessage(incomingMessage, context);
    } else{
        System.out.println("socketClosed = true");
        socketClosed = true;
    }
}

它不如3.6版本好,因为内存消耗较高。