Combine sorted-set membership and scores with weighted union/intersection/difference while respecting cost, version, and Cluster locality.

ZUNION/ZINTER/ZDIFF and Weighted Ranking Aggregation

Choose hashes, Redis JSON, or many keys from structure, update/query patterns, expiration granularity, memory/cardinality, indexing, ACL boundaries, and migration evidence.

Advanced150–185 minutesWeighted aggregation labRedis Open Source 8.10.1Free/local-firstLast reviewed: September 6, 2026

Learning outcomes

AtlasMart maintains several ranked signals—sales, conversion quality, and support satisfaction—and wants combined rankings plus cohort intersections. Redis can derive new sorted sets or return derived results directly, but weighted aggregation has precise score semantics and multi-key/topology cost.

01

Use ZUNION, ZINTER, and ZDIFF with exact membership semantics.

02

Apply WEIGHTS and SUM/MIN/MAX aggregation and interpret resulting scores.

03

Explain the Redis 8.8+ COUNT aggregate as a version-sensitive extension.

04

Measure input cardinality/result size instead of treating multi-set algebra as cheap.

05

Plan Redis Cluster hash-slot locality for multi-key sorted-set operations.

Exact lab baseline

All Chapter 06 mandatory labs reuse the disposable Chapter 01 environment: Redis Open Source 8.10.1 from Docker Official Image redis:8.10.1, container atlasmart-redis-ch01, standalone topology, host publication 127.0.0.1:6379, TLS disabled only because traffic stays on loopback, default ACL user disabled, named ACL users atlasmart-app and academy-admin, logical database 0, AOF with appendfsync everysec plus RDB snapshots, persistent /data volume, and no explicit Redis maxmemory limit or eviction policy. The primary interface is the redis-cli shipped in the same pinned image. Mandatory examples use only bounded synthetic keys under atlasmart:ch06:*.

1. Union merges membership and aggregates overlapping scores

ZUNION returns every member that appears in at least one input sorted set. When a member appears in multiple inputs, the default SUM aggregate combines its weighted scores.

redis-cli · plain union
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app DEL atlasmart:ch06:sales atlasmart:ch06:qualitydocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZADD atlasmart:ch06:sales 10 a 20 b 30 cdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZADD atlasmart:ch06:quality 4 b 8 c 16 ddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZUNION 2 atlasmart:ch06:sales atlasmart:ch06:quality WITHSCORES

The result contains a, b, c, and d. Members b and c receive sums from both inputs. The result is returned to the client; STORE variants persist a derived key.

2. WEIGHTS transform each input before aggregation

WEIGHTS multiplies each input score by its corresponding factor before the aggregate is applied. This is mathematically simple but operationally dangerous if stakeholders treat arbitrary weights as objective truth. Normalize input scales deliberately.

redis-cli · weighted union
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZUNION 2 atlasmart:ch06:sales atlasmart:ch06:quality WEIGHTS 0.7 0.3 AGGREGATE SUM WITHSCORESdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZUNION 2 atlasmart:ch06:sales atlasmart:ch06:quality WEIGHTS 1 1 AGGREGATE MAX WITHSCORESdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZUNION 2 atlasmart:ch06:sales atlasmart:ch06:quality WEIGHTS 1 1 AGGREGATE MIN WITHSCORES

SUM combines contributions; MAX/MIN choose the maximum/minimum transformed score among inputs where the member exists. Weight choice belongs in a versioned ranking policy, not in an unexplained command literal.

3. Intersection changes membership before score aggregation

ZINTER keeps only members present in every input. It then applies weights and aggregation to those surviving members. This is useful for “rank only customers who belong to every required cohort,” but the smallest input set and number of inputs affect worst-case cost.

redis-cli · intersection evidence
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZINTER 2 atlasmart:ch06:sales atlasmart:ch06:quality WITHSCORESdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZINTER 2 atlasmart:ch06:sales atlasmart:ch06:quality WEIGHTS 2 1 AGGREGATE SUM WITHSCORESdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZCARD atlasmart:ch06:salesdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZCARD atlasmart:ch06:quality

Only b and c survive the example. The documentation classifies ZINTER as a slow command because cost grows with input/result cardinality.

4. Difference is membership subtraction, not score subtraction

ZDIFF returns members in the first sorted set that do not appear in subsequent sets. It does not subtract scores.

redis-cli · difference semantics
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZDIFF 2 atlasmart:ch06:sales atlasmart:ch06:quality WITHSCORESdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZDIFF 2 atlasmart:ch06:quality atlasmart:ch06:sales WITHSCORES

The direction matters. “sales minus quality” and “quality minus sales” are different membership sets.

5. Redis 8.8+ COUNT aggregate is version-sensitive

Current Redis 8.10.1 documentation includes AGGREGATE COUNT for ZUNION/ZINTER and their STORE variants, added in Redis 8.8. With COUNT, the resulting score reflects how many input sets contributed the member rather than SUM/MIN/MAX score arithmetic. Because this is newer than many Redis deployments and client wrappers, check INFO server, COMMAND INFO, and client support before relying on it.

6. Version evidence before using newer aggregation

Do not infer command options from a course screenshot. Ask the server you are connected to.

redis-cli · capability evidence
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app INFO serverdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app COMMAND INFO ZUNIONdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZUNION 2 atlasmart:ch06:sales atlasmart:ch06:quality AGGREGATE COUNT WITHSCORES

In the pinned 8.10.1 lab, COUNT should be available. On an older server or managed service with different compatibility, the command may fail even if your client library has a method signature for it.

7. Wrong approach: huge synchronous aggregation on hot global keys

Multi-key sorted-set algebra can read many members and construct a large result. Returning millions of derived members to one client can consume CPU, memory, network bandwidth, and tail-latency budget. Storing a derived result can also duplicate substantial memory.

redis-cli · bounded cost evidence—not a benchmark claim
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZCARD atlasmart:ch06:salesdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZCARD atlasmart:ch06:qualitydocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app MEMORY USAGE atlasmart:ch06:salesdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app MEMORY USAGE atlasmart:ch06:qualitydocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZUNION 2 atlasmart:ch06:sales atlasmart:ch06:quality WITHSCORES

Repair by bounding cohorts, precomputing intentionally, sampling/benchmarking realistic sizes, or redesigning the ranking pipeline. Never extrapolate this tiny fixture's latency to production.

8. Stored versus returned results

ZUNION/ZINTER/ZDIFF return results. STORE variants write a destination key and replace its previous value. Stored derived rankings introduce lifecycle questions: who refreshes them, how long are they valid, what happens during partial update, and how are stale results removed? Derived keys are not automatically synchronized views.

9. Redis Cluster: all participating keys must be routable together

Multi-key commands in Redis Cluster have slot-locality constraints. Hash tags can deliberately co-locate related keys, for example atlasmart:{region:az}:sales and atlasmart:{region:az}:quality. That enables same-region aggregation but can also concentrate traffic. Do not add a common global hash tag merely to make every multi-key command legal; that can destroy distribution.

10. Ranking policy table

Choice Meaning Risk to document
SUM add transformed scores scale dominance / double-counting
MIN weakest contributing score different meaning from “minimum across all entities”
MAX strongest contributing score can ignore weaker signals
COUNT (8.8+) number of contributing inputs version/client compatibility
ZDIFF membership subtraction direction matters; scores not subtracted

11. Reproducible weighted-ranking lab

Build three small signals, derive union/intersection/difference, then remove them.

redis-cli · three-signal lab
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app DEL atlasmart:ch06:lab:s1 atlasmart:ch06:lab:s2 atlasmart:ch06:lab:s3docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZADD atlasmart:ch06:lab:s1 10 u:a 20 u:b 30 u:cdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZADD atlasmart:ch06:lab:s2 5 u:b 9 u:c 11 u:ddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZADD atlasmart:ch06:lab:s3 1 u:c 2 u:d 3 u:edocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZUNION 3 atlasmart:ch06:lab:s1 atlasmart:ch06:lab:s2 atlasmart:ch06:lab:s3 WEIGHTS 1 2 3 AGGREGATE SUM WITHSCORESdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZINTER 3 atlasmart:ch06:lab:s1 atlasmart:ch06:lab:s2 atlasmart:ch06:lab:s3 WITHSCORESdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app ZDIFF 2 atlasmart:ch06:lab:s1 atlasmart:ch06:lab:s2 WITHSCORES

Verification: only u:c appears in all three. Difference s1−s2 contains only u:a. Compute expected weighted scores manually before trusting any ranking policy.

12. Production judgment

Weighted sorted-set algebra is appropriate for bounded, explicit ranking derivations whose score scales and membership meaning are understood. It is not a substitute for analytical databases, offline feature pipelines, or full ranking evaluation. Benchmark realistic cardinality/skew, measure output size and p99 latency, define derived-key freshness, and make Cluster locality deliberate. Treat new options such as COUNT as version-gated.

13. Summary and next step

Union, intersection, and difference combine membership; weights and aggregation define derived scores. Next, we use sorted sets as operational secondary indexes for rate limits, schedulers, expiration indexes, and other access paths—while separating the index from the source of truth.

Check your understanding

  1. What membership does ZINTER return?
  2. What happens before SUM/MIN/MAX when WEIGHTS are used?
  3. Does ZDIFF subtract numeric scores?
  4. When was AGGREGATE COUNT added?
  5. Why do Cluster hash tags need restraint?
Review the answers

Only members present in every input set.

Each input score is multiplied by its corresponding weight.

No. It subtracts membership from the first input.

Redis 8.8.

Co-locating everything under one hash tag can create a hot slot and defeat distribution.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.