Skip to content

Commit

Permalink
Implement zDiff and zDiffWithScores API (#367)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfmejia authored May 6, 2021
1 parent e3454bf commit 2352e26
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 0 deletions.
53 changes: 53 additions & 0 deletions redis/src/main/scala/zio/redis/api/SortedSets.scala
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,58 @@ trait SortedSets {
command.run((key, range))
}

/**
* Subtract multiple sorted sets and return members.
*
* @param inputKeysNum Number of input keys
* @param key Key of a sorted set
* @param keys Keys of other sorted sets
* @return Chunk of differences between the first and successive input sorted sets.
*/
final def zDiff[K: Schema, M: Schema](
inputKeysNum: Long,
key: K,
keys: K*
): ZIO[RedisExecutor, RedisError, Chunk[M]] = {
val command =
RedisCommand(
ZDiff,
Tuple2(
LongInput,
NonEmptyList(ArbitraryInput[K]())
),
ChunkOutput(ArbitraryOutput[M]())
)
command.run((inputKeysNum, (key, keys.toList)))
}

/**
* Subtract multiple sorted sets and return members and their associated score.
*
* @param inputKeysNum Number of input keys
* @param key Key of a sorted set
* @param keys Keys of other sorted sets
* @return Chunk of differences and scores between the first and successive input sorted sets.
*/
final def zDiffWithScores[K: Schema, M: Schema](
inputKeysNum: Long,
key: K,
keys: K*
): ZIO[RedisExecutor, RedisError, Chunk[MemberScore[M]]] = {
val command =
RedisCommand(
ZDiff,
Tuple3(
LongInput,
NonEmptyList(ArbitraryInput[K]()),
ArbitraryInput[String]()
),
ChunkTuple2Output(ArbitraryOutput[M](), DoubleOutput)
.map(_.map { case (m, s) => MemberScore(s, m) })
)
command.run((inputKeysNum, (key, keys.toList), WithScores.stringify))
}

/**
* Subtract multiple sorted sets and store the resulting sorted set in a destination key.
*
Expand Down Expand Up @@ -810,6 +862,7 @@ private[redis] object SortedSets {
final val ZAdd = "ZADD"
final val ZCard = "ZCARD"
final val ZCount = "ZCOUNT"
final val ZDiff = "ZDIFF"
final val ZDiffStore = "ZDIFFSTORE"
final val ZIncrBy = "ZINCRBY"
final val ZInter = "ZINTER"
Expand Down
65 changes: 65 additions & 0 deletions redis/src/test/scala/zio/redis/SortedSetsSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,71 @@ trait SortedSetsSpec extends BaseSpec {
} yield assert(count)(equalTo(0L))
}
),
suite("zDiff")(
testM("empty sets") {
for {
key1 <- uuid
key2 <- uuid
key3 <- uuid
diff <- zDiff[String, String](3, key1, key2, key3)
} yield assert(diff)(isEmpty)
},
testM("non-empty set with empty set") {
for {
key1 <- uuid
key2 <- uuid
_ <- zAdd(key1)(
MemberScore(1d, "a"),
MemberScore(2d, "b")
)
diff <- zDiff[String, String](2, key1, key2)
} yield assert(diff)(hasSameElements(Chunk("a", "b")))
},
testM("non-empty sets") {
for {
key1 <- uuid
key2 <- uuid
_ <- zAdd(key1)(
MemberScore(1d, "a"),
MemberScore(2d, "b"),
MemberScore(3d, "c")
)
_ <- zAdd(key2)(MemberScore(1d, "a"), MemberScore(2d, "b"))
diff <- zDiff[String, String](2, key1, key2)
} yield assert(diff)(hasSameElements(Chunk("c")))
}
),
suite("zDiffWithScores")(
testM("empty sets") {
for {
key1 <- uuid
key2 <- uuid
key3 <- uuid
diff <- zDiffWithScores[String, String](3, key1, key2, key3)
} yield assert(diff)(isEmpty)
},
testM("non-empty set with empty set") {
for {
key1 <- uuid
key2 <- uuid
_ <- zAdd(key1)(MemberScore(1d, "a"), MemberScore(2d, "b"))
diff <- zDiffWithScores[String, String](2, key1, key2)
} yield assert(diff)(hasSameElements(Chunk(MemberScore(1d, "a"), MemberScore(2d, "b"))))
},
testM("non-empty sets") {
for {
key1 <- uuid
key2 <- uuid
_ <- zAdd(key1)(
MemberScore(1d, "a"),
MemberScore(2d, "b"),
MemberScore(3d, "c")
)
_ <- zAdd(key2)(MemberScore(1d, "a"), MemberScore(2d, "b"))
diff <- zDiffWithScores[String, String](2, key1, key2)
} yield assert(diff)(hasSameElements(Chunk(MemberScore(3d, "c"))))
}
),
suite("zDiffStore")(
testM("empty sets") {
for {
Expand Down

0 comments on commit 2352e26

Please sign in to comment.