JSON 查询语法对比

下面是一个更复杂的 JSON 查询示例,展示了如何在 MongoDB、PostgreSQL、jq 和 JMESPath 以及JSONPath中进行查询。假设我们有一个更深层次的 JSON 数据结构:

假设 JSON 数据如下:

{
  "store": {
    "book": [
      { 
        "category": "fiction", 
        "author": "J.K. Rowling", 
        "title": "Harry Potter", 
        "price": 29.99,
        "publisher": { 
          "name": "Bloomsbury", 
          "location": "London"
        },
        "reviews": [
          { "user": "John", "rating": 5 },
          { "user": "Alice", "rating": 4 }
        ]
      },
      { 
        "category": "fiction", 
        "author": "J.R.R. Tolkien", 
        "title": "The Hobbit", 
        "price": 19.99,
        "publisher": { 
          "name": "HarperCollins", 
          "location": "New York"
        },
        "reviews": [
          { "user": "Bob", "rating": 4 },
          { "user": "Charlie", "rating": 3 }
        ]
      },
      { 
        "category": "non-fiction", 
        "author": "Yuval Noah Harari", 
        "title": "Sapiens", 
        "price": 14.99,
        "publisher": { 
          "name": "HarperCollins", 
          "location": "New York"
        },
        "reviews": [
          { "user": "David", "rating": 5 },
          { "user": "Emma", "rating": 4 }
        ]
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 199.99
    }
  }
}

查询要求:

  1. 查找所有价格大于 20 的书籍。
  2. 查找出版社是 "HarperCollins" 且评分超过 4 的书籍。
  3. 查找书籍的价格,并返回对应的出版社名称。

MongoDB 查询

MongoDB 查询语法可以非常灵活。假设你要查询价格大于 20 且出版社为 "HarperCollins" 的书籍,并且书籍的平均评分要大于 4:

db.store.find({
  "book": {
    "$elemMatch": {
      "price": { "$gt": 20 },
      "publisher.name": "HarperCollins",
      "reviews.rating": { "$gt": 4 }
    }
  }
})

PostgreSQL 查询

在 PostgreSQL 中,假设数据存储在一个 jsonb 字段中,我们可以查询价格大于 20 的书籍,并且查询符合特定出版社名称和评分条件的书籍:

SELECT * 
FROM your_table
WHERE 
  jsonb_array_elements(data->'store'->'book')
  @> '{"price": 19.99}'
  
  AND 
  jsonb_extract_path_text(
    jsonb_array_elements(data->'store'->'book'),
    'publisher', 'name'
  ) = 'HarperCollins'

  AND 
  jsonb_array_elements(data->'store'->'book'->'reviews') 
  @> '{"rating": 5}';

jq 查询

jq 查询语言可以非常简洁,以下是查找价格大于 20 且出版社为 "HarperCollins" 且至少有一个评论评分大于 4 的书籍:

jq '.store.book[] | select(.price > 20 and .publisher.name == "HarperCollins" and (.reviews[] | .rating > 4))' input.json

Python JMESPath 查询

在 Python 中使用 JMESPath 库查询价格大于 20 且评论评分大于 4 的书籍,并返回出版社名称:

import jmespath

data = …

result = jmespath.search(
  'store.book[?price > `20` && publisher.name == `HarperCollins` && reviews[?rating > `4`]]', 
  data
)
print(result)

JSONPath 查询

$.store.book[?(@.price > 20 && @.publisher.name == 'HarperCollins' && @.reviews[?(@.rating > 4)])]

JSONPath的语法噪音比JMESPath更多一些,实际上JMESPath也更为强大一些,综合来说JMESPath还是比JSONPath是更好的选择。

结果

这些查询将返回以下匹配的书籍:

[
  { 
    "category": "fiction", 
    "author": "J.R.R. Tolkien", 
    "title": "The Hobbit", 
    "price": 19.99,
    "publisher": { 
      "name": "HarperCollins", 
      "location": "New York"
    },
    "reviews": [
      { "user": "Bob", "rating": 4 },
      { "user": "Charlie", "rating": 3 }
    ]
  }
]

这个更复杂的查询示例涵盖了如何在不同的数据源中进行多层次、带有多个条件的查询。

posted @ 2025-03-30 11:33  ffl  阅读(80)  评论(0)    收藏  举报