ArangoDB - 如何使用图形实现自定义推荐引擎?
ArangoDB - how to implement a custom recommendation engine using graph?
假设我们有一个食品数据库,例如:
item1 = {name: 'item1', tags: ['mexican', 'spicy']};
item2 = {name: 'item2', tags: ['sweet', 'chocolate', 'nuts']};
item3 = {name: 'item3', tags: ['sweet', 'vanilla', 'cold']};
我们有一个用户在寻找食物推荐,他们在其中指出了他们对某些标签的偏好权重:
foodPref = {sweet: 4, chocolate: 11}
现在我们需要计算每个项目的得分并推荐最好的项目:
item1 score = 0 (doesn't contain any of the tags user is looking for)
item2 score = 4 (contains the tag 'sweet')
item3 score = 15 (contains the tag 'sweet' and 'chocolate')
我已将问题建模为图表:
获得推荐的正确方法是什么——自定义遍历对象,或者只是使用 AQL 进行过滤和计数,或者只是在 Foxx(javascript 层)中实现它?
另外,你能帮忙提供一个你建议的方法的示例实现吗?
提前致谢!
首先,让我们按照您指定的方式创建集合及其内容。我们将添加第二个用户。
db._create("user")
db._create("tags")
db._create("dishes")
db.user.save({_key: 'user1'})
db.user.save({_key: 'user2'})
db.tags.save({_key: 'sweet'})
db.tags.save({_key: 'chocolate'})
db.tags.save({_key: 'vanilla'})
db.tags.save({_key: 'spicy'})
db.dishes.save({_key: 'item1'})
db.dishes.save({_key: 'item2'})
db.dishes.save({_key: 'item3'})
现在让我们用它们的边创建边集合:
db._createEdgeCollection("userPreferences")
db._createEdgeCollection("dishTags")
db.userPreferences.save("user/user1", "tags/sweet", {score: 4})
db.userPreferences.save("user/user1", "tags/chocolate", {score: 11})
db.userPreferences.save("user/user2", "tags/sweet", {score: 27})
db.userPreferences.save("user/user2", "tags/vanilla", {score: 7})
db.dishTags.save("tags/sweet", "dishes/item2", {score: 4});
db.dishTags.save("tags/sweet", "dishes/item3", {score: 7})
db.dishTags.save("tags/chocolate", "dishes/item2", {score: 2})
db.dishTags.save("tags/vanilla", "dishes/item3", {score: 3})
db.dishTags.save("tags/spicy", "dishes/item1", {score: 666})
我们的关系是这样的:
user-[userPreferences]->tags-[dishTags]->dishes
找出user1
喜欢什么可以用这个查询来完成:
FOR v, e IN 1..2 OUTBOUND "user/user1" userPreferences, dishTags
RETURN {item: v, connection: e}
如果你现在想找到user1
最喜欢的所有菜肴:
FOR v, e IN 2..2 OUTBOUND "user/user1" userPreferences, dishTags
FILTER e.score > 4 RETURN v
我们过滤 score
属性。
现在我们要查找与 user1
具有相同偏好的另一个用户:
FOR v, e IN 2..2 ANY "user/user1" userPreferences RETURN v
我们进入 ANY
方向(向前和向后),但只对 userPreferences
边缘集合感兴趣,否则 2..2 也将使用盘子。我们现在这样做的方式。我们返回用户集合以查找具有相似偏好的用户。
创建 Foxx 服务是否是一个好的选择取决于个人喜好。如果您想在服务器端组合和过滤结果,Foxx 非常有用,因此客户端通信较少。如果你喜欢将你的应用程序放在微服务之上而不是数据库查询之上,你也可以使用它。然后,您的应用程序可能不会包含特定于数据库的代码 - 它仅 operates with the microservice 作为其后端。可能有 Foxx
的用例
一般来说,没有 "correct" 方式 - 由于性能、代码清洁度、可扩展性等原因,您可能更喜欢不同的方式。
假设我们有一个食品数据库,例如:
item1 = {name: 'item1', tags: ['mexican', 'spicy']};
item2 = {name: 'item2', tags: ['sweet', 'chocolate', 'nuts']};
item3 = {name: 'item3', tags: ['sweet', 'vanilla', 'cold']};
我们有一个用户在寻找食物推荐,他们在其中指出了他们对某些标签的偏好权重:
foodPref = {sweet: 4, chocolate: 11}
现在我们需要计算每个项目的得分并推荐最好的项目:
item1 score = 0 (doesn't contain any of the tags user is looking for)
item2 score = 4 (contains the tag 'sweet')
item3 score = 15 (contains the tag 'sweet' and 'chocolate')
我已将问题建模为图表:
获得推荐的正确方法是什么——自定义遍历对象,或者只是使用 AQL 进行过滤和计数,或者只是在 Foxx(javascript 层)中实现它?
另外,你能帮忙提供一个你建议的方法的示例实现吗?
提前致谢!
首先,让我们按照您指定的方式创建集合及其内容。我们将添加第二个用户。
db._create("user")
db._create("tags")
db._create("dishes")
db.user.save({_key: 'user1'})
db.user.save({_key: 'user2'})
db.tags.save({_key: 'sweet'})
db.tags.save({_key: 'chocolate'})
db.tags.save({_key: 'vanilla'})
db.tags.save({_key: 'spicy'})
db.dishes.save({_key: 'item1'})
db.dishes.save({_key: 'item2'})
db.dishes.save({_key: 'item3'})
现在让我们用它们的边创建边集合:
db._createEdgeCollection("userPreferences")
db._createEdgeCollection("dishTags")
db.userPreferences.save("user/user1", "tags/sweet", {score: 4})
db.userPreferences.save("user/user1", "tags/chocolate", {score: 11})
db.userPreferences.save("user/user2", "tags/sweet", {score: 27})
db.userPreferences.save("user/user2", "tags/vanilla", {score: 7})
db.dishTags.save("tags/sweet", "dishes/item2", {score: 4});
db.dishTags.save("tags/sweet", "dishes/item3", {score: 7})
db.dishTags.save("tags/chocolate", "dishes/item2", {score: 2})
db.dishTags.save("tags/vanilla", "dishes/item3", {score: 3})
db.dishTags.save("tags/spicy", "dishes/item1", {score: 666})
我们的关系是这样的:
user-[userPreferences]->tags-[dishTags]->dishes
找出user1
喜欢什么可以用这个查询来完成:
FOR v, e IN 1..2 OUTBOUND "user/user1" userPreferences, dishTags
RETURN {item: v, connection: e}
如果你现在想找到user1
最喜欢的所有菜肴:
FOR v, e IN 2..2 OUTBOUND "user/user1" userPreferences, dishTags
FILTER e.score > 4 RETURN v
我们过滤 score
属性。
现在我们要查找与 user1
具有相同偏好的另一个用户:
FOR v, e IN 2..2 ANY "user/user1" userPreferences RETURN v
我们进入 ANY
方向(向前和向后),但只对 userPreferences
边缘集合感兴趣,否则 2..2 也将使用盘子。我们现在这样做的方式。我们返回用户集合以查找具有相似偏好的用户。
创建 Foxx 服务是否是一个好的选择取决于个人喜好。如果您想在服务器端组合和过滤结果,Foxx 非常有用,因此客户端通信较少。如果你喜欢将你的应用程序放在微服务之上而不是数据库查询之上,你也可以使用它。然后,您的应用程序可能不会包含特定于数据库的代码 - 它仅 operates with the microservice 作为其后端。可能有 Foxx
的用例一般来说,没有 "correct" 方式 - 由于性能、代码清洁度、可扩展性等原因,您可能更喜欢不同的方式。