【问题标题】:Fetching data from MongoDb with Spring使用 Spring 从 MongoDb 获取数据
【发布时间】:2017-11-02 15:25:18
【问题描述】:

我正在测试一个基于酒店搜索的场景。 所以我做了 3 个模型类,分别是 Hotel、Room 和 Availability

以下是我们使用的三个模型类。

Hotel.java

@Document(collection = "酒店") 公共类酒店{

@Id
private String id;

private String name;

private Long pincode;

@Field("roomCategoryDocs")
private Object roomCategoryDocs;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Long getPincode() {
    return pincode;
}

public void setPincode(Long pincode) {
    this.pincode = pincode;
}

public Object getRoomCategoryDocs() {
    return roomCategoryDocs;
}

public void setRoomCategoryDocs(Object roomCategoryDocs) {
    this.roomCategoryDocs = roomCategoryDocs;
}

@Override
public String toString() {
    return String.format("Hotel [id=%s, name=%s, pincode=%s, roomCategoryDocs=%s]", id, name, pincode,
            roomCategoryDocs);
}

}

Room.java

@Document(collection = "房间") 公共课室{

@Id
private String id;

private String frontImg;

private String category;

private ObjectId hotelId;

@Field("availabilityDocs")
private Object availabilityDocs;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getFrontImg() {
    return frontImg;
}

public void setFrontImg(String frontImg) {
    this.frontImg = frontImg;
}

public String getCategory() {
    return category;
}

public void setCategory(String category) {
    this.category = category;
}

public ObjectId getHotelId() {
    return hotelId;
}

public void setHotelId(ObjectId hotelId) {
    this.hotelId = hotelId;
}

public Object getAvailabilityDocs() {
    return availabilityDocs;
}

public void setAvailabilityDocs(Object availabilityDocs) {
    this.availabilityDocs = availabilityDocs;
}

@Override
public String toString() {
    return String.format("Room [id=%s, frontImg=%s, category=%s, hotelId=%s, availabilityDocs=%s]", id, frontImg,
            category, hotelId, availabilityDocs);
}

}

可用性.java

@Document(collection = "房间") 公共类可用性{

@Id
private String id;

private ObjectId roomId;

private Integer availability;

private Double rate;

private String date;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public ObjectId getRoomId() {
    return roomId;
}

public void setRoomId(ObjectId roomId) {
    this.roomId = roomId;
}

public Integer getAvailability() {
    return availability;
}

public void setAvailability(Integer availability) {
    this.availability = availability;
}

public Double getRate() {
    return rate;
}

public void setRate(Double rate) {
    this.rate = rate;
}

public String getDate() {
    return date;
}

public void setDate(String date) {
    this.date = date;
}

@Override
public String toString() {
    return String.format("Availability [id=%s, roomId=%s, availability=%s, rate=%s, date=%s]", id, roomId,
            availability, rate, date);
}

}

这些存储在两个 mongodb 集合中,一个用于 Hotel,另一个用于 Room 和可用性。

下面是我们从中获取数据的控制器类的方法

@GetMapping(value = "/hotel") 公共列表 getAllHotel() {

    Aggregation agg = newAggregation(match(Criteria.where("pincode").lt(800080)),
            lookup("rooms", "_id", "hotelId", "roomCategoryDocs"), unwind("roomCategoryDocs", true),
            lookup("rooms", "roomCategoryDocs._id", "roomId", "roomCategoryDocs.availabilityDocs"),
            unwind("roomCategoryDocs", true), 
            group("_id").first("name").as("name").last("pincode").as("pincode").push("roomCategoryDocs").as("roomCategoryDocs")

    );

    // Convert the aggregation result into a List
    AggregationResults<Hotel> groupResults = mongoTemplate.aggregate(agg, "Hotels", Hotel.class);
    List<Hotel> result = groupResults.getMappedResults();

    return result;

}

现在,在获取酒店数据时,我们正在获取所有数据,包括房间和空房情况。

我们得到的输出:

[
  {
    "id": "59fabce1acd8be143417b101",
    "name": "Elegance",
    "pincode": 700042,
    "availabilityDocs": [
      {
        "id": "59fabe39acd8be143417b103",
        "frontImg": "google.com/1234",
        "category": "Deluxe",
        "hotelId": {
          "timestamp": 1509604577,
          "machineIdentifier": 11327678,
          "processIdentifier": 5172,
          "counter": 1552641,
          "timeSecond": 1509604577,
          "time": 1509604577000,
          "date": 1509604577000
        },
        "availabilityDocs1": [
          {
            "id": "59fabf66acd8be14344a2df3",
            "roomId": {
              "timestamp": 1509604921,
              "machineIdentifier": 11327678,
              "processIdentifier": 5172,
              "counter": 1552643,
              "timeSecond": 1509604921,
              "time": 1509604921000,
              "date": 1509604921000
            },
            "availability": 10,
            "rate": 4000,
            "date": "2017-10-11"
          },
          {
                 "id": "59fae259acd8be264cf4430f",
                  "roomId": {
                         "timestamp": 1509604921,
                            "machineIdentifier": 11327678,
                            "processIdentifier": 5172,
                            "counter": 1552643,
                            "timeSecond": 1509604921,
                            "time": 1509604921000,
                            "date": 1509604921000
                        },
                        "availability": 11,
                        "rate": 4001,
                        "date": "2017-10-12"
                }
        ]
      }
    ]
  }
]

但是现在我们被困在一个问题上,那就是根据日期属性进行搜索。

预期输出:

这里我们只想获取 2017 年 11 月 10 日的数据。

  {
    "id": "59fabce1acd8be143417b101",
    "name": "Elegance",
    "pincode": 700042,
    "availabilityDocs": [
      {
        "id": "59fabe39acd8be143417b103",
        "frontImg": "google.com/1234",
        "category": "Deluxe",
        "hotelId": {
          "timestamp": 1509604577,
          "machineIdentifier": 11327678,
          "processIdentifier": 5172,
          "counter": 1552641,
          "timeSecond": 1509604577,
          "time": 1509604577000,
          "date": 1509604577000
        },
        "availabilityDocs1": [
          {
            "id": "59fabf66acd8be14344a2df3",
            "roomId": {
              "timestamp": 1509604921,
              "machineIdentifier": 11327678,
              "processIdentifier": 5172,
              "counter": 1552643,
              "timeSecond": 1509604921,
              "time": 1509604921000,
              "date": 1509604921000
            },
            "availability": 10,
            "rate": 4000,
            "date": "2017-10-11"
          }
}

下面是json集合示例 酒店系列:

{ "_id" : ObjectId("59fabce1acd8be143417b101"), "name" : "Elegance", "pincode" : NumberLong(700042), "_class" : "com.lara.mongodb.domain.Hotel" }

房间集合示例:

{ "_id" : ObjectId("59fabf66acd8be14344a2df3"), "roomId" : ObjectId("59fabe39acd8be143417b103"), "availability" : 10, "rate" : 4000, "date" : "2017-10-11", "_class" : "com.lara.mongodb.domain.Availability" }

我愿意接受有关设计的任何建议以及您可能有的任何其他想法,因为我是新手。 任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 可用性实体是某个集合的嵌入文档,还是您将结果写入单独的集合。如果您可以添加一个 json 示例来说明您的酒店和房间集合的外观,这也会有所帮助。
  • 嗨,Alex,我们只使用 2 个集合,即酒店和客房。我们的收藏中没有嵌入任何内容。我还添加了您要求的 json 示例。

标签: java json spring mongodb


【解决方案1】:

老实说,我对如何在同一个集合中写入两个实体感到有些困惑。从您添加的示例集合中,我可以说缺少一个。但是把这个放在一边。我使用您的最终结果作为切入点。所以我从:

{
    "id": "59fabce1acd8be143417b101",
    "name": "Elegance",
    "pincode": 700042,
    "availabilityDocs": [
      {
        "id": "59fabe39acd8be143417b103",
        "frontImg": "google.com/1234",
        "category": "Deluxe",
        "hotelId": {
          "timestamp": 1509604577,
          "machineIdentifier": 11327678,
          "processIdentifier": 5172,
          "counter": 1552641,
          "timeSecond": 1509604577,
          "time": 1509604577000,
          "date": 1509604577000
        },
        "availabilityDocs1": [
          {
            "id": "59fabf66acd8be14344a2df3",
            "roomId": {
              "timestamp": 1509604921,
              "machineIdentifier": 11327678,
              "processIdentifier": 5172,
              "counter": 1552643,
              "timeSecond": 1509604921,
              "time": 1509604921000,
              "date": 1509604921000
            },
            "availability": 10,
            "rate": 4000,
            "date": "2017-10-11"
          },
          {
                 "id": "59fae259acd8be264cf4430f",
                  "roomId": {
                         "timestamp": 1509604921,
                            "machineIdentifier": 11327678,
                            "processIdentifier": 5172,
                            "counter": 1552643,
                            "timeSecond": 1509604921,
                            "time": 1509604921000,
                            "date": 1509604921000
                        },
                        "availability": 11,
                        "rate": 4001,
                        "date": "2017-10-12"
                }
        ]
      }
    ]
  }

这是您进行聚合后的结果。现在您只需要2017-10-11 可用的房间。但在您的结果数组中,您会同时获得“2017-10-12”和“2017-10-11”。

所以如果我有上述结果,你必须添加以下内容:

{
    $unwind: "$availabilityDocs"
},
{
    $unwind: "$availabilityDocs.availabilityDocs1"
},
{
    $match: {
        "availabilityDocs.availabilityDocs1.date" : "2017-10-11"
        }
}

【讨论】:

  • 我们不会将实体存储在单个集合中。在 mongoDb 中,我们将其称为文档,我们可以将不同类型的文档存储在单个 Collection 中,这是面向文档的数据库的优势之一。关于你的建议,我已经尝试过这个,但由于某种原因,Spring 无法识别 '"$availabilityDocs.availabilityDocs1" ' 展开的语法并返回一个空数组。
  • 我知道那个哥们。虽然你的描述有不一致的地方。在您的春季聚合中,您编写 push("roomCategoryDocs").as("roomCategoryDocs") 但您说您得到的结果是字段名称:“availabilityDocs”。所以再次检查您的描述并更正它。如果春季放松对您不起作用,请检查结果。可能是字段名称不同
猜你喜欢
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 2021-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多