Skip to content

查询和聚合

FxJSON 提供了强大的数据查询和聚合功能,包括内置的查询构建器和聚合器,以及高性能的遍历和数据访问,让您能够高效地从 JSON 数据中提取和分析信息。

提示: FxJSON 提供了内置的 node.Query() 查询构建器和 node.Aggregate() 聚合器(详见 API 文档),本指南展示了多种数据查询和聚合的方法。

基础数据查询

使用内置查询构建器

go
func builtinQueryExample() {
    productsData := `{
        "products": [
            {"id": 1, "name": "笔记本电脑", "price": 5999, "category": "电子产品", "stock": 10, "rating": 4.5, "active": true},
            {"id": 2, "name": "智能手机", "price": 2999, "category": "电子产品", "stock": 25, "rating": 4.3, "active": true},
            {"id": 3, "name": "蓝牙耳机", "price": 299, "category": "配件", "stock": 50, "rating": 4.1, "active": false},
            {"id": 4, "name": "机械键盘", "price": 699, "category": "配件", "stock": 15, "rating": 4.7, "active": true},
            {"id": 5, "name": "显示器", "price": 1999, "category": "电子产品", "stock": 8, "rating": 4.4, "active": true}
        ]
    }`

    node := fxjson.FromBytes([]byte(productsData))
    products := node.Get("products")

    // 使用查询构建器查找符合条件的产品
    results, err := products.Query().
        Where("price", ">", 1000).
        Where("active", "=", true).
        Where("category", "=", "电子产品").
        SortBy("price", "desc").
        Limit(3).
        ToSlice()
    
    if err != nil {
        fmt.Printf("查询错误: %v\n", err)
        return
    }

    fmt.Printf("找到 %d 个符合条件的产品:\n", len(results))
    for _, product := range results {
        name := product.Get("name").StringOr("")
        price := product.Get("price").FloatOr(0)
        fmt.Printf("- %s: ¥%.0f\n", name, price)
    }

    // 使用聚合器计算统计信息
    stats, err := products.Aggregate().
        Count("total_products").
        Sum("price", "total_value").
        Avg("price", "avg_price").
        Max("rating", "highest_rating").
        Min("stock", "lowest_stock").
        Execute(products)
    
    if err != nil {
        fmt.Printf("聚合错误: %v\n", err)
        return
    }

    fmt.Println("统计信息:")
    for key, value := range stats {
        fmt.Printf("- %s: %v\n", key, value)
    }
}

简单条件查询

go
func basicQuery() {
    productsData := `{
        "products": [
            {"id": 1, "name": "笔记本电脑", "price": 5999, "category": "电子产品", "stock": 10, "rating": 4.5},
            {"id": 2, "name": "智能手机", "price": 2999, "category": "电子产品", "stock": 25, "rating": 4.3},
            {"id": 3, "name": "蓝牙耳机", "price": 299, "category": "配件", "stock": 50, "rating": 4.1},
            {"id": 4, "name": "机械键盘", "price": 699, "category": "配件", "stock": 15, "rating": 4.7},
            {"id": 5, "name": "显示器", "price": 1999, "category": "电子产品", "stock": 8, "rating": 4.4}
        ]
    }`

    node := fxjson.FromBytes([]byte(productsData))
    products := node.Get("products")

    // 查找高价商品(价格大于2000)
    var highPriceProducts []fxjson.Node
    products.ArrayForEach(func(index int, product fxjson.Node) bool {
        price := product.Get("price").FloatOr(0)
        if price > 2000 {
            highPriceProducts = append(highPriceProducts, product)
        }
        return true
    })

    fmt.Printf("高价商品数量: %d\n", len(highPriceProducts))
    for _, product := range highPriceProducts {
        name := product.Get("name").StringOr("")
        price := product.Get("price").FloatOr(0)
        fmt.Printf("- %s: ¥%.0f\n", name, price)
    }

    // 查找电子产品中库存充足的商品
    var electronicProducts []fxjson.Node
    products.ArrayForEach(func(index int, product fxjson.Node) bool {
        category := product.Get("category").StringOr("")
        stock := product.Get("stock").IntOr(0)
        if category == "电子产品" && stock > 10 {
            electronicProducts = append(electronicProducts, product)
        }
        return true
    })

    fmt.Printf("库存充足的电子产品: %d\n", len(electronicProducts))

    // 查找名称包含"键盘"的商品
    var keyboardProducts []fxjson.Node
    products.ArrayForEach(func(index int, product fxjson.Node) bool {
        name := product.Get("name").StringOr("")
        if strings.Contains(name, "键盘") {
            keyboardProducts = append(keyboardProducts, product)
        }
        return true
    })

    fmt.Printf("键盘类商品: %d\n", len(keyboardProducts))
}

复杂条件查询

go
func advancedQuery() {
    salesData := `{
        "sales": [
            {"id": 1, "product": "笔记本", "amount": 5999, "quantity": 2, "date": "2024-01-15", "region": "北京"},
            {"id": 2, "product": "手机", "amount": 2999, "quantity": 1, "date": "2024-01-16", "region": "上海"},
            {"id": 3, "product": "耳机", "amount": 299, "quantity": 5, "date": "2024-01-17", "region": "广州"},
            {"id": 4, "product": "键盘", "amount": 699, "quantity": 3, "date": "2024-01-18", "region": "北京"},
            {"id": 5, "product": "鼠标", "amount": 199, "quantity": 10, "date": "2024-01-19", "region": "深圳"},
            {"id": 6, "product": "显示器", "amount": 1999, "quantity": 1, "date": "2024-01-20", "region": "上海"}
        ]
    }`

    node := fxjson.FromBytes([]byte(salesData))
    sales := node.Get("sales")

    // 查找北京和上海的销售记录
    var beijingShanghaiSales []fxjson.Node
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        region := sale.Get("region").StringOr("")
        if region == "北京" || region == "上海" {
            beijingShanghaiSales = append(beijingShanghaiSales, sale)
        }
        return true
    })
    fmt.Printf("北京和上海的销售记录: %d\n", len(beijingShanghaiSales))

    // 查找非北京的销售记录
    var nonBeijingSales []fxjson.Node
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        region := sale.Get("region").StringOr("")
        if region != "北京" {
            nonBeijingSales = append(nonBeijingSales, sale)
        }
        return true
    })
    fmt.Printf("非北京的销售记录: %d\n", len(nonBeijingSales))

    // 复杂组合查询:金额大于1000或数量大于等于5,且不在深圳
    var complexResults []fxjson.Node
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        amount := sale.Get("amount").FloatOr(0)
        quantity := sale.Get("quantity").IntOr(0)
        region := sale.Get("region").StringOr("")
        
        if (amount > 1000 || quantity >= 5) && region != "深圳" {
            complexResults = append(complexResults, sale)
        }
        return true
    })
    fmt.Printf("复杂查询结果: %d\n", len(complexResults))

    // 日期范围查询
    var dateRangeResults []fxjson.Node
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        date := sale.Get("date").StringOr("")
        if date >= "2024-01-16" && date <= "2024-01-18" {
            dateRangeResults = append(dateRangeResults, sale)
        }
        return true
    })
    fmt.Printf("指定日期范围销售: %d\n", len(dateRangeResults))
}

数据排序和分页

自定义排序

go
func sortingAndPaging() {
    productsData := `{
        "products": [
            {"id": 1, "name": "笔记本电脑", "price": 5999, "rating": 4.5},
            {"id": 2, "name": "智能手机", "price": 2999, "rating": 4.3},
            {"id": 3, "name": "蓝牙耳机", "price": 299, "rating": 4.1},
            {"id": 4, "name": "机械键盘", "price": 699, "rating": 4.7}
        ]
    }`

    node := fxjson.FromBytes([]byte(productsData))
    products := node.Get("products")

    // 收集所有产品到切片中
    var productList []fxjson.Node
    products.ArrayForEach(func(index int, product fxjson.Node) bool {
        productList = append(productList, product)
        return true
    })

    // 按价格降序排列
    sort.Slice(productList, func(i, j int) bool {
        priceI := productList[i].Get("price").FloatOr(0)
        priceJ := productList[j].Get("price").FloatOr(0)
        return priceI > priceJ
    })

    fmt.Println("按价格降序排列:")
    for i, product := range productList {
        if i >= 3 { // 只显示前3个
            break
        }
        name := product.Get("name").StringOr("")
        price := product.Get("price").FloatOr(0)
        fmt.Printf("%d. %s: ¥%.0f\n", i+1, name, price)
    }

    // 按评分降序排列
    sort.Slice(productList, func(i, j int) bool {
        ratingI := productList[i].Get("rating").FloatOr(0)
        ratingJ := productList[j].Get("rating").FloatOr(0)
        return ratingI > ratingJ
    })

    fmt.Println("\n按评分降序排列:")
    for i, product := range productList {
        name := product.Get("name").StringOr("")
        rating := product.Get("rating").FloatOr(0)
        fmt.Printf("%d. %s: %.1f\n", i+1, name, rating)
    }

    // 分页处理
    pageSize := 2
    totalPages := (len(productList) + pageSize - 1) / pageSize
    
    fmt.Printf("\n分页结果 (每页%d个,共%d页):\n", pageSize, totalPages)
    for page := 0; page < totalPages; page++ {
        start := page * pageSize
        end := start + pageSize
        if end > len(productList) {
            end = len(productList)
        }
        
        fmt.Printf("第%d页:\n", page+1)
        for i := start; i < end; i++ {
            name := productList[i].Get("name").StringOr("")
            fmt.Printf("  - %s\n", name)
        }
    }
}

数据聚合分析

基础聚合计算

go
func basicAggregation() {
    salesData := `{
        "sales": [
            {"product": "笔记本", "amount": 5999, "quantity": 2, "region": "北京"},
            {"product": "手机", "amount": 2999, "quantity": 5, "region": "上海"},
            {"product": "耳机", "amount": 299, "quantity": 10, "region": "广州"},
            {"product": "键盘", "amount": 699, "quantity": 3, "region": "北京"},
            {"product": "鼠标", "amount": 199, "quantity": 8, "region": "深圳"}
        ]
    }`

    node := fxjson.FromBytes([]byte(salesData))
    sales := node.Get("sales")

    // 计算总销售额
    totalAmount := 0.0
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        amount := sale.Get("amount").FloatOr(0)
        totalAmount += amount
        return true
    })

    // 计算平均销售额
    recordCount := sales.Len()
    avgAmount := totalAmount / float64(recordCount)

    // 找出最大和最小销售额
    maxAmount := 0.0
    minAmount := math.Inf(1)
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        amount := sale.Get("amount").FloatOr(0)
        if amount > maxAmount {
            maxAmount = amount
        }
        if amount < minAmount {
            minAmount = amount
        }
        return true
    })

    fmt.Printf("总销售额: ¥%.0f\n", totalAmount)
    fmt.Printf("平均销售额: ¥%.2f\n", avgAmount)
    fmt.Printf("最大单笔: ¥%.0f\n", maxAmount)
    fmt.Printf("最小单笔: ¥%.0f\n", minAmount)
    fmt.Printf("销售记录数: %d\n", recordCount)

    // 计算总销售数量
    totalQuantity := 0.0
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        quantity := sale.Get("quantity").FloatOr(0)
        totalQuantity += quantity
        return true
    })

    avgQuantity := totalQuantity / float64(recordCount)
    fmt.Printf("总销售数量: %.0f\n", totalQuantity)
    fmt.Printf("平均销售数量: %.2f\n", avgQuantity)
}

分组聚合分析

go
func groupAggregation() {
    salesData := `{
        "sales": [
            {"product": "笔记本", "amount": 5999, "quantity": 2, "region": "北京", "category": "电子产品"},
            {"product": "手机", "amount": 2999, "quantity": 5, "region": "上海", "category": "电子产品"},
            {"product": "耳机", "amount": 299, "quantity": 10, "region": "广州", "category": "配件"},
            {"product": "键盘", "amount": 699, "quantity": 3, "region": "北京", "category": "配件"},
            {"product": "鼠标", "amount": 199, "quantity": 8, "region": "深圳", "category": "配件"},
            {"product": "显示器", "amount": 1999, "quantity": 1, "region": "上海", "category": "电子产品"}
        ]
    }`

    node := fxjson.FromBytes([]byte(salesData))
    sales := node.Get("sales")

    // 按地区分组聚合
    regionStats := make(map[string]map[string]float64)
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        region := sale.Get("region").StringOr("")
        amount := sale.Get("amount").FloatOr(0)
        quantity := sale.Get("quantity").FloatOr(0)

        if regionStats[region] == nil {
            regionStats[region] = make(map[string]float64)
        }

        regionStats[region]["total_amount"] += amount
        regionStats[region]["total_quantity"] += quantity
        regionStats[region]["count"] += 1

        return true
    })

    fmt.Println("按地区分组统计:")
    for region, stats := range regionStats {
        fmt.Printf("%s:\n", region)
        fmt.Printf("  总销售额: ¥%.0f\n", stats["total_amount"])
        fmt.Printf("  总数量: %.0f\n", stats["total_quantity"])
        fmt.Printf("  订单数: %.0f\n", stats["count"])
        fmt.Printf("  平均单价: ¥%.2f\n", stats["total_amount"]/stats["count"])
        fmt.Println()
    }

    // 按类别分组聚合
    categoryStats := groupBy(sales, "category", []string{"amount", "quantity"})
    fmt.Println("按类别分组统计:")
    for category, stats := range categoryStats {
        fmt.Printf("%s: 总额¥%.0f, 总量%.0f, 订单%.0f\n", 
            category, stats["amount_sum"], stats["quantity_sum"], stats["count"])
    }
}

func groupBy(node fxjson.Node, groupField string, aggregateFields []string) map[string]map[string]float64 {
    groups := make(map[string]map[string]float64)

    node.ArrayForEach(func(index int, item fxjson.Node) bool {
        groupValue := item.Get(groupField).StringOr("unknown")

        if groups[groupValue] == nil {
            groups[groupValue] = make(map[string]float64)
        }

        // 计数
        groups[groupValue]["count"] += 1

        // 聚合指定字段
        for _, field := range aggregateFields {
            value := item.Get(field).FloatOr(0)
            groups[groupValue][field+"_sum"] += value
            groups[groupValue][field+"_avg"] = groups[groupValue][field+"_sum"] / groups[groupValue]["count"]
            
            if groups[groupValue][field+"_max"] < value || groups[groupValue]["count"] == 1 {
                groups[groupValue][field+"_max"] = value
            }
            
            if groups[groupValue][field+"_min"] > value || groups[groupValue]["count"] == 1 {
                groups[groupValue][field+"_min"] = value
            }
        }

        return true
    })

    return groups
}

数据分析示例

销售数据分析

go
func salesAnalysis() {
    // 生成模拟销售数据
    salesData := generateSalesData()
    node := fxjson.FromBytes([]byte(salesData))
    sales := node.Get("sales")

    // 时间序列分析
    monthlyStats := analyzeMonthlyTrends(sales)
    fmt.Println("月度趋势分析:")
    for month, stats := range monthlyStats {
        fmt.Printf("%s: 销售额¥%.0f, 增长率%.2f%%\n", 
            month, stats["amount"], stats["growth_rate"])
    }

    // 产品分析
    productPerformance := analyzeProductPerformance(sales)
    fmt.Println("\n产品性能分析:")
    for _, product := range productPerformance {
        fmt.Printf("产品: %s, 销售额: ¥%.0f, 利润率: %.2f%%\n",
            product["name"], product["revenue"], product["profit_margin"])
    }

    // 地区分析
    regionAnalysis := analyzeRegionalPerformance(sales)
    fmt.Println("\n区域分析:")
    for region, metrics := range regionAnalysis {
        fmt.Printf("%s: 市场份额%.2f%%, 平均订单¥%.2f\n",
            region, metrics["market_share"], metrics["avg_order"])
    }
}

func analyzeMonthlyTrends(sales fxjson.Node) map[string]map[string]float64 {
    monthlyData := make(map[string][]float64)
    
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        date := sale.Get("date").StringOr("")
        amount := sale.Get("amount").FloatOr(0)
        
        if len(date) >= 7 {
            month := date[:7] // YYYY-MM
            monthlyData[month] = append(monthlyData[month], amount)
        }
        return true
    })

    results := make(map[string]map[string]float64)
    var previousAmount float64
    
    for month, amounts := range monthlyData {
        total := 0.0
        for _, amount := range amounts {
            total += amount
        }
        
        growthRate := 0.0
        if previousAmount > 0 {
            growthRate = (total - previousAmount) / previousAmount * 100
        }
        
        results[month] = map[string]float64{
            "amount":      total,
            "count":       float64(len(amounts)),
            "avg_order":   total / float64(len(amounts)),
            "growth_rate": growthRate,
        }
        
        previousAmount = total
    }
    
    return results
}

func analyzeProductPerformance(sales fxjson.Node) []map[string]interface{} {
    productStats := make(map[string]map[string]float64)
    
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        product := sale.Get("product").StringOr("")
        amount := sale.Get("amount").FloatOr(0)
        cost := sale.Get("cost").FloatOr(amount * 0.7) // 假设成本为70%
        
        if productStats[product] == nil {
            productStats[product] = make(map[string]float64)
        }
        
        productStats[product]["revenue"] += amount
        productStats[product]["cost"] += cost
        productStats[product]["orders"] += 1
        
        return true
    })

    var results []map[string]interface{}
    for product, stats := range productStats {
        profit := stats["revenue"] - stats["cost"]
        profitMargin := 0.0
        if stats["revenue"] > 0 {
            profitMargin = profit / stats["revenue"] * 100
        }
        
        results = append(results, map[string]interface{}{
            "name":          product,
            "revenue":       stats["revenue"],
            "profit":        profit,
            "profit_margin": profitMargin,
            "orders":        stats["orders"],
            "avg_order":     stats["revenue"] / stats["orders"],
        })
    }
    
    return results
}

func analyzeRegionalPerformance(sales fxjson.Node) map[string]map[string]float64 {
    regionStats := make(map[string]map[string]float64)
    totalRevenue := 0.0
    
    // 第一遍:收集基础数据
    sales.ArrayForEach(func(index int, sale fxjson.Node) bool {
        region := sale.Get("region").StringOr("")
        amount := sale.Get("amount").FloatOr(0)
        
        if regionStats[region] == nil {
            regionStats[region] = make(map[string]float64)
        }
        
        regionStats[region]["revenue"] += amount
        regionStats[region]["orders"] += 1
        totalRevenue += amount
        
        return true
    })
    
    // 第二遍:计算比率和平均值
    for region, stats := range regionStats {
        stats["market_share"] = (stats["revenue"] / totalRevenue) * 100
        stats["avg_order"] = stats["revenue"] / stats["orders"]
    }
    
    return regionStats
}

func generateSalesData() string {
    return `{
        "sales": [
            {"product": "笔记本", "amount": 5999, "date": "2024-01-15", "region": "北京", "cost": 4199},
            {"product": "手机", "amount": 2999, "date": "2024-01-16", "region": "上海", "cost": 2099},
            {"product": "耳机", "amount": 299, "date": "2024-02-17", "region": "广州", "cost": 209},
            {"product": "键盘", "amount": 699, "date": "2024-02-18", "region": "北京", "cost": 489},
            {"product": "鼠标", "amount": 199, "date": "2024-03-19", "region": "深圳", "cost": 139}
        ]
    }`
}

性能优化

大数据量查询优化

go
func optimizedQuerying() {
    // 生成大量数据进行性能测试
    largeDataset := generateLargeDataset(10000)
    node := fxjson.FromBytes([]byte(largeDataset))
    products := node.Get("products")
    
    // 使用早期终止优化查询
    start := time.Now()
    var expensiveProducts []fxjson.Node
    products.ArrayForEach(func(index int, product fxjson.Node) bool {
        price := product.Get("price").FloatOr(0)
        if price > 5000 {
            expensiveProducts = append(expensiveProducts, product)
            // 如果找到足够的结果,可以提前终止
            if len(expensiveProducts) >= 10 {
                return false // 终止遍历
            }
        }
        return true
    })
    duration := time.Since(start)
    
    fmt.Printf("找到 %d 个昂贵商品,耗时: %v\n", len(expensiveProducts), duration)
    
    // 使用批量处理优化大数据查询
    batchSize := 1000
    var results []fxjson.Node
    
    start = time.Now()
    totalCount := products.Len()
    for i := 0; i < totalCount; i += batchSize {
        end := i + batchSize
        if end > totalCount {
            end = totalCount
        }
        
        // 处理当前批次
        for j := i; j < end; j++ {
            product := products.Index(j)
            category := product.Get("category").StringOr("")
            if category == "电子产品" {
                results = append(results, product)
            }
        }
    }
    batchDuration := time.Since(start)
    
    fmt.Printf("批量处理找到 %d 个电子产品,耗时: %v\n", len(results), batchDuration)
}

func generateLargeDataset(count int) string {
    var products []string
    categories := []string{"电子产品", "配件", "服装", "食品", "图书"}
    
    for i := 0; i < count; i++ {
        price := 100 + (i % 10000)
        category := categories[i%len(categories)]
        
        product := fmt.Sprintf(`{
            "id": %d,
            "name": "商品%d",
            "price": %d,
            "category": "%s",
            "stock": %d
        }`, i, i, price, category, 10+(i%100))
        
        products = append(products, product)
    }
    
    return fmt.Sprintf(`{"products": [%s]}`, strings.Join(products, ","))
}

通过这些查询和聚合功能,FxJSON 让您能够高效地从 JSON 数据中提取有价值的信息和洞察,满足各种数据分析需求。

基于 MIT 许可证发布