Example #1
0
func dumpSetOp(conn *client.Conn, args []string) {
	op, err := setop.NewSetOpParser(args[2]).Parse()
	if err != nil {
		fmt.Println(err)
	} else {
		for _, res := range conn.SetExpression(setop.SetExpression{Dest: []byte(args[1]), Op: op}) {
			printSetOpRes(res)
		}
	}
}
Example #2
0
func getRecommendations(w http.ResponseWriter, r *http.Request, c *client.Conn) {
	uid := mux.Vars(r)["user_id"]
	var request common.RecommendationsRequest
	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		panic(err)
	}
	// Create a set operation that returns the union of the likers of all objects we have liked, just returning the user key
	likersOp := &setop.SetOp{
		Merge: setop.First,
		Type:  setop.Union,
	}
	// For each object we have liked, add the likers of that flavor as a source to the union of likers
	for _, obj := range c.Slice(uLikesKey(uid), nil, nil, true, true) {
		likersOp.Sources = append(likersOp.Sources, setop.SetOpSource{Key: oLikesKey(string(obj.Key))})
	}
	// Create a set operation that returns the union of all things liked by all likers of objects we liked, returning the sum of the likes for each object
	objectsOp := &setop.SetOp{
		Merge: setop.FloatSum,
		Type:  setop.Union,
	}
	// For each user in the union of users having liked something we like
	for _, user := range c.SetExpression(setop.SetExpression{
		Op: likersOp,
	}) {
		// If the user is not us
		if string(user.Key) != uid {
			// Fetch the number of objects we have both liked
			similarity := len(c.SetExpression(setop.SetExpression{
				Code: fmt.Sprintf("(I:First %v %v)", string(uLikesKey(string(user.Key))), string(uLikesKey(uid))),
			}))
			// And weight the user according to how many commonalities we have
			weight := math.Log(float64(similarity + 1))
			// Add the objects liked by this user, weighed this much, as a source
			objectsOp.Sources = append(objectsOp.Sources, setop.SetOpSource{Key: uLikesKey(string(user.Key)), Weight: &weight})
		}
	}
	// If we want to filter on active objects
	if request.Actives != "" {
		// Create an operation on the simple Union and the active objects
		objectsOp = &setop.SetOp{
			Merge: setop.First,
			Sources: []setop.SetOpSource{
				setop.SetOpSource{
					SetOp: objectsOp,
				},
				setop.SetOpSource{
					Key: activeObjectsKey,
				},
			},
		}
		// And make it of the correct type
		if request.Actives == common.Reject {
			objectsOp.Type = setop.Difference
		} else if request.Actives == common.Intersect {
			objectsOp.Type = setop.Intersection
		}
	}
	// If we want to filter on viewed objects
	if request.Viewed != "" {
		// Create an operation on the previous operation and the viewed objects
		objectsOp = &setop.SetOp{
			Merge: setop.First,
			Sources: []setop.SetOpSource{
				setop.SetOpSource{
					SetOp: objectsOp,
				},
				setop.SetOpSource{
					Key: uViewsKey(uid),
				},
			},
		}
		// And make it of the correct type
		if request.Viewed == common.Reject {
			objectsOp.Type = setop.Difference
		} else if request.Viewed == common.Intersect {
			objectsOp.Type = setop.Intersection
		}
	}
	// Finally, fetch the wanted number of recommendations
	var result []common.Message
	for _, item := range c.SetExpression(setop.SetExpression{
		Op: objectsOp,
	}) {
		w := godCommon.MustDecodeFloat64(item.Values[0])
		i := sort.Search(len(result), func(i int) bool {
			return w > result[i].Weight
		})
		if i < len(result) {
			if len(result) < request.Num {
				result = append(result[:i], append([]common.Message{common.Message{
					Object: string(item.Key),
					Weight: w,
				}}, result[i:]...)...)
			} else {
				if i > 0 {
					result = append(result[:i], append([]common.Message{common.Message{
						Object: string(item.Key),
						Weight: w,
					}}, result[i:len(result)-1]...)...)
				} else {
					result = append([]common.Message{common.Message{
						Object: string(item.Key),
						Weight: w,
					}}, result[i:len(result)-1]...)
				}
			}
		} else {
			if len(result) < request.Num {
				result = append(result, common.Message{
					Object: string(item.Key),
					Weight: w,
				})
			}
		}
	}
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	if err := json.NewEncoder(w).Encode(result); err != nil {
		panic(err)
	}
}