SInter returns the members of the set resulting from the intersection of all the given sets.
(ctx *Context, txn *db.Transaction)
| 221 | |
| 222 | // SInter returns the members of the set resulting from the intersection of all the given sets. |
| 223 | func SInter(ctx *Context, txn *db.Transaction) (OnCommit, error) { |
| 224 | var members [][]byte |
| 225 | setsIter := make([]*db.SetIter, len(ctx.Args)) |
| 226 | for i, key := range ctx.Args { |
| 227 | set, err := txn.Set([]byte(key)) |
| 228 | if err != nil { |
| 229 | if err == db.ErrTypeMismatch { |
| 230 | return nil, ErrTypeMismatch |
| 231 | } |
| 232 | return nil, errors.New("ERR " + err.Error()) |
| 233 | } |
| 234 | // If the set corresponding to key does not exist, it is processed as an empty set |
| 235 | if !set.Exists() { |
| 236 | return BytesArray(ctx.Out, members), nil |
| 237 | } |
| 238 | siter, err := set.Iter() |
| 239 | if err != nil { |
| 240 | return nil, errors.New("ERR " + err.Error()) |
| 241 | } |
| 242 | defer siter.Iter.Close() |
| 243 | setsIter[i] = siter |
| 244 | } |
| 245 | |
| 246 | h := MinHeap(setsIter) |
| 247 | heap.Init(&h) |
| 248 | var last []byte |
| 249 | k := len(h) //k-way merge |
| 250 | n := k |
| 251 | for len(h) != 0 { |
| 252 | min := h[0].Value() |
| 253 | if last == nil || bytes.Equal(last, min) { |
| 254 | n-- |
| 255 | } else { |
| 256 | n = k - 1 |
| 257 | } |
| 258 | last = min |
| 259 | |
| 260 | // it is a member of intersection if there are k equal values continuously |
| 261 | if n == 0 { |
| 262 | members = append(members, min) |
| 263 | } |
| 264 | |
| 265 | if err := h[0].Iter.Next(); err != nil { |
| 266 | return nil, err |
| 267 | } |
| 268 | if h[0].Valid() { |
| 269 | heap.Fix(&h, 0) |
| 270 | } else { |
| 271 | heap.Remove(&h, 0) |
| 272 | } |
| 273 | } |
| 274 | return BytesArray(ctx.Out, members), nil |
| 275 | } |
| 276 | |
| 277 | // SDiff returns the members of the set resulting from the difference between the first set and all the successive sets. |
| 278 | func SDiff(ctx *Context, txn *db.Transaction) (OnCommit, error) { |