【问题标题】:MongoDB: Getting data from an json array if the values exist in a particular orderMongoDB:如果值以特定顺序存在,则从 json 数组中获取数据
【发布时间】:2016-10-26 03:29:09
【问题描述】:

我正在使用 pymongo。我的收藏中的文档如下所示。

{
  train_name: <Train1>
  train_number: <#>
  details: [
      {
        station_name: <station1>
        arrives: <time>
        departs: <time>
        distance_travelled: <distance>
        halt: <>
      }

     {
        station_name: <station2>
        arrives: <time>
        departs: <time>
        distance_travelled: <distance>
        halt: <>
      }

    {
        station_name: <station3>
        arrives: <time>
        departs: <time>
        distance_travelled: <distance>
        halt: <>
      }

   ]

我想查询此数据库以查找两个车站之间的可用列车。也就是说,用户将提供一个“源”站和一个“目的地”,我需要一个查询来返回“源”和“目的地”之间的所有可用列车

从这个示例文档中,如果用户提供,我应该得到“Train1”的结果:

  1. 来源 - “station1”
    目的地 - “station2”
  2. 来源 - “station1”
    目的地 - “station3”

如果用户提供了'Train1',则不应返回:

  1. 来源 - “station2”
    目的地 - “station1”
  2. 来源 - “station3”
    目的地 - “station1”

简而言之,我只想在值以特定顺序出现在 json 列表中时查询和获取结果。

到目前为止,我有这个

cursor = db.trains.find({"detail.station_name": {"$all": [source, destination]}},
                                {"train_name": True, "train_no": True, "_id": False})

但它不尊重顺序。它给了我所有同时具有“来源”和“目的地”的火车名称,而不管它们的顺序如何。

我希望我的问题很清楚。我是 mongodb 的新手。因此,我们将不胜感激任何帮助。

谢谢。

【问题讨论】:

  • 嗨,您的数据中缺少火车方向。即您的第一个示例 (source:station1) 和第二个示例 (destination: station1) 之间有什么区别?您可以在文档中添加一些信息或更改schema 以指示方向。此外,您的查询本质上是在询问“查找与station1 AND station2 匹配的所有电台名称,仅返回字段train_nametrain_no。”
  • 对不起,如果我的问题有任何混淆。在上面的示例文档中,“station1”是旅程“开始”的地方,“station3”是“Train1”旅程“结束”的地方。所以数据是“详细”列表已经按正确的顺序排序。如果它在“station1”(可以是任何源站)和“station3”(可以是任何目标站)之间运行,我只需要获取这个火车名称。我不确定如何将文档架构更改为指示的方向。你能详细说明一下吗?谢谢。

标签: python mongodb pymongo


【解决方案1】:

所以数据是“详细”列表已经按正确的顺序排序。

如果details 值已经按正确顺序排序,您可以使用以下命令进行查询:

db.trains.find( 
          {$and:[
            {"details.0.station_name":"station1"},         
            {"details.station_name":"station2"}
          ]}, 
          {"train_name":1, train_number:1, _id:0}
);

您在哪里搜索“查找第一个车站名称为 station1 并且任何其他车站包括 station2 的所有火车”。

如上所述,根据您的用例/应用程序处理数组索引可能并不总是理想的。即除了第一个之外,您并不总是知道订购号。

我不确定如何将文档架构更改为指示的方向。请您详细说明一下

您可以使用多种data modeling 来利用和优化您经常使用的查询。作为领域专家,您是做出此决定的最佳人选。 但是,以下是替代示例:

您可以包含sourceStationdestinationStation 的字段,以便轻松查询起点/终点站:

{
    sourceStation: {
        id: 001,
        name: "station1"
    },
    destinationStation:{
        id: 010,
        name: "station3"
    },
    details: [
      { station_name: "station1",
        ... },
      { station_name: "station2",
        ... },
      { station_name: "station3",
        ...}
    ],
    train_name: "Train1", 
    train_no: 88,
    arrives: <time>, 
    departs: <time>, 
    distance_travelled: <distance>
}

或者您可以将旅程拆分为单独的文档以获取旅程的粒度:

{
    _id: ObjectId(...),
    sourceStation: {
        id: 001,
        name: "station1"
    },
    destinationStation:{
        id: 009,
        name: "station2"
    },
    train_name: "Train1", 
    train_no: 88,
    arrives: "0900", 
    departs: "0910", 
    distance_travelled: "3kms"
}, 

{
    _id: ObjectId(...),
    sourceStation: {
        id: 009,
        name: "station2"
    },
    destinationStation:{
        id: 010,
        name: "station3"
    },
    train_name: "Train1", 
    train_no: 88,
    arrives: "0930", 
    departs: "0940", 
    distance_travelled: "4kms"
}

另请参阅Data Model Examples and Patterns 以获取更多灵感。

我是 mongodb 的新手。因此,我们将不胜感激。

我建议在MongoDB University 注册免费在线课程。尤其是涵盖架构设计和查询的 M101 开发人员课程。

【讨论】:

  • 感谢万的详细解释。我正在调查你发布的这个查询。 db.trains.find( {$and:[ {"details.0.station_name":"station1"}, {"details.station_name":"station2"} ]}, {"train_name":1, train_number:1, _id:0});这里假设 station1 必须是第一个站点,但情况可能并非如此。我正在寻找一个查询,如果在“station1”和“station2”之间运行,它将给我火车。 (这里的station1和station2不一定是起点和终点,分别)
  • 条件是station 2应该在station1之后。如果可以进行查询,请您帮我看看,否则我会按照您的建议研究其他模式选项。谢谢。
  • 理想的解决方案是重新设计您的模式模型。您当然可以尝试使用已弃用的 map-reduce$where,但您不会使用 NoSQL 模式灵活性的正确概念并且会降低性能。您还可以使用任何supported MongoDB drivers 来获取数组索引。
猜你喜欢
  • 2021-10-05
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-25
  • 2019-03-30
  • 2023-03-04
  • 1970-01-01
相关资源
最近更新 更多