ArangoDB - как реализовать пользовательский механизм рекомендаций, используя график?

Допустим, у нас есть база данных продуктов питания, таких как:

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)?

Кроме того, можете ли вы помочь с примером реализации предложенных вами методов?

Заранее спасибо!

1 ответ

Решение

Сначала давайте создадим коллекции и их содержимое так, как вы их указали. Мы добавим второго пользователя.

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 отлично подходит, если вы хотите объединить и отфильтровать результаты на стороне сервера, поэтому общение с клиентами будет меньше. Вы также можете использовать его, если вы хотите поместить свое приложение скорее на микросервисы, чем на db-запросы. В этом случае ваше приложение может остаться свободным от кода, специфичного для базы данных, - оно работает только с микросервисом в качестве бэкенда Там могут быть случаи, когда Foxx

В общем, нет "правильного" способа - есть разные способы, которые вы можете предпочесть выше других из-за производительности, чистоты кода, масштабируемости и т. Д.

Другие вопросы по тегам