使用Cloudant从JSON数组中检索JSON对象

时间:2018-11-29 13:56:26

标签: json nested couchdb cloudant

我每40分钟执行一次API调用,以检索车队中每辆车的当前状态信息。每个调用都会向Cloudant数据库添加一个新的JSON文档。每个JSON文档定义了许多城市中许多位置的每辆汽车的当前可用性状态。当前数据库中大约有2200个JSON文档。所有JSON文档都有一个名为payload的字段,其中包含所有信息。它是各种各样的对象。我不想检索整个payload对象数组,而是想通过查询仅 检索所需的信息(因此,该数组仅一个或多个对象)。但是,我很难起草仅产生所需数据的查询。

下面,我将详细解释我的问题: 将JSON文档保存到Cloudant时,在文档中定义了timestamp_id参数定义为等于此时间戳。下面,我显示了这些JSON文档的简化版本:

 {
  "_id": "1540914946026",
  "_rev": "3-c1834c8a230cf772e41bbcb9cf6b682e",
  "timestamp": 1540914946026,
  "datetime": "2018-10-30 15:55:46",
  "payload": [
    {
      "cityName": "Abcoude",
      "locations": [
        {
          "address": "asterlaan 28",
          "geoPoint": {
            "latitude": 52.27312,
            "longitude": 4.96768
          },
          "cars": [
            {
              "mod": "BMW",
              "state": "FREE"
            }
          ]
        }
      ],
      "availableCars": 1,
      "occupiedCars": 0
    },
    {
      "cityName": "Alkmaar",
      "locations": [
        {
          "address": "Aert de Gelderlaan 14",
          "geoPoint": {
            "latitude": 52.63131,
            "longitude": 4.72329
          },
          "cars": [
            {
              "model": "Volswagen",
              "state": "FREE"
            }
          ]
        },
        {
          "address": "Ardennenstraat 49",
          "geoPoint": {
            "latitude": 52.66721,
            "longitude": 4.76046
          },
          "cars": [
            {
              "mod": "BMW",
              "state": "FREE"
            }
          ]
        },
        {
          "address": "Beneluxplein 7",
          "geoPoint": {
            "latitude": 52.65356,
            "longitude": 4.75817
          },
          "cars": [
            {
              "mod": "BMW",
              "state": "FREE"
            }
          ]
        },
        {
          "address": "Dr. Schaepmankade 1",
          "geoPoint": {
            "latitude": 52.62595,
            "longitude": 4.75122
          },
          "cars": [
            {
              "mod": "BMW",
              "state": "OCCUPIED"
            }
          ]
        },
        {
          "address": "Kennemerstraatweg",
          "geoPoint": {
            "latitude": 52.62909,
            "longitude": 4.74226
          },
          "cars": [
            {
              "model": "Mercedes",
              "state": "FREE"
            }
          ]
        },
        {
          "address": "NS Station Alkmaar Noord/Parkeerterrein Noord",
          "geoPoint": {
            "latitude": 52.64366,
            "longitude": 4.7627
          },
          "cars": [
            {
              "model": "Tesla",
              "state": "FREE"
            }
          ]
        },
        {
          "address": "NS Station Alkmaar/Stationsweg 56",
          "geoPoint": {
            "latitude": 52.6371,
            "longitude": 4.73935
          },
          "cars": [
            {
              "model": "Tesla",
              "state": "FREE"
            }
          ]
        },
        {
          "address": "Oude Hoeverweg",
          "geoPoint": {
            "latitude": 52.63943,
            "longitude": 4.72928
          },
          "cars": [
            {
              "model": "Tesla",
              "state": "FREE"
            }
          ]
        },
        {
          "address": "Parkeerterrein Wortelsteeg",
          "geoPoint": {
            "latitude": 52.63048,
            "longitude": 4.75487
          },
          "cars": [
            {
              "model": "Tesla",
              "state": "OCCUPIED"
            }
          ]
        },
        {
          "address": "Schoklandstraat 38",
          "geoPoint": {
            "latitude": 52.65812,
            "longitude": 4.75359
          },
          "cars": [
            {
              "model": "Volkswagen",
              "state": "FREE"
            }
          ]
        }
      ],
      "availableCars": 8,
      "occupiedCars": 2
    }
  ]
}

如您所见,payload字段是一个包含多个对象的数组(仅供参考:该数组中的每个对象都代表一个特定的城市:有​​1600个城市,因此{{1}内有1600个嵌套对象}数组)。此外,在提到的1600个对象的每一个内部,其他数组和对象也再次嵌套在内部。对于payload数组中的所有对象,第一个字段为payload

此外,还有一个嵌套数组cityName(在locations数组的1600个对象中),它们表示特定城市中的所有地址。 payload数组的大小可以为1到600,即每个城市1到600个嵌套对象/地址。 locations数组的所有对象中的最后两个字段是payloadavailableCars

我想查询文档以查看在特定时间间隔内特定城市有多少辆汽车可供使用。为此:

  • 我必须指定一个 start 时间戳(或occupiedCars)和一个 end 时间戳,仅在此间隔内生成JSON文档。
  • 此外,我将需要在JSON文档中仅按id指定一个或多个特定城市(有1600个城市),然后获取可用车数cityName和{ {1}}用于这些城市。

例如,在此简化示例中,我想查询从1540914946026(历时)到现在的阿尔克马尔市的状态信息(availableCars和`occupiedCars)。我想得到以下结果:

occupiedCars

这只是一个示例,实际上,我希望能够查询其他城市,或者一起查询几个城市,然后为每个城市获取可用车数availableCars和占用的汽车数量{ "id":"1540914946026", "cityName":"Alkmaar", "availableCars":8, "occupiedCars":2 }

有人可以帮助我定义查询和索引以获取上述结果吗?我可以使用cloudant查询吗?

1 个答案:

答案 0 :(得分:2)

您的数据模型无法发挥Cloudant的优势。让每个文档分组更改并一起访问的数据。有效载荷数组中的项目最好存储为离散文档。

如果您发现文档内的数据子集越来越多地出现在阵列中,这是一个警告信号,表明您的数据模型不理想:文档现在易变且正在增长(结果可能存在更新冲突),并且可以访问随着时间的流逝,Cloudant不再仅检索文档的一部分,因此变得越来越麻烦。此外,Cloudant的文档大小有一个限制(1M),因此,使用建议的模型,您也可能会达到该限制,并且应用程序将停止运行。

话虽如此,可以创建一个视图索引,让您发出有效载荷的每个组件,这将使您可以按城市查找数据-但该解决方案仍受上述所有限制(文档模型)易变,文档变大等)。

经验法则:小文件。尽可能采用不可变的模型。记录更改或作为一个单元进行访问的组数据。