From 3ad739612fb800810d9b6cbde829373c8c41df0c Mon Sep 17 00:00:00 2001 From: Ondrej Fiedler Date: Fri, 25 Aug 2017 15:08:03 +0200 Subject: [PATCH] Support returnProperties and includedProperties parameters of ListItems and ListUsers. Send User-Agent HTTP header. --- lib/recombee_api_client.rb | 11 ++-- lib/recombee_api_client/api/add_bookmark.rb | 4 +- .../api/add_cart_addition.rb | 4 +- .../api/add_detail_view.rb | 6 +- lib/recombee_api_client/api/add_purchase.rb | 4 +- lib/recombee_api_client/api/add_rating.rb | 4 +- .../api/insert_to_group.rb | 2 +- .../api/insert_to_series.rb | 2 +- .../api/item_based_recommendation.rb | 53 ++++++++++------- lib/recombee_api_client/api/list_groups.rb | 2 +- .../api/list_item_bookmarks.rb | 2 +- .../api/list_item_cart_additions.rb | 2 +- .../api/list_item_detail_views.rb | 2 +- .../api/list_item_purchases.rb | 2 +- .../api/list_item_ratings.rb | 2 +- lib/recombee_api_client/api/list_items.rb | 56 +++++++++++++++++- lib/recombee_api_client/api/list_series.rb | 2 +- .../api/list_user_bookmarks.rb | 2 +- .../api/list_user_cart_additions.rb | 2 +- .../api/list_user_detail_views.rb | 2 +- .../api/list_user_purchases.rb | 2 +- .../api/list_user_ratings.rb | 2 +- lib/recombee_api_client/api/list_users.rb | 59 ++++++++++++++++++- lib/recombee_api_client/api/merge_users.rb | 9 +-- lib/recombee_api_client/api/reset_database.rb | 2 +- .../api/user_based_recommendation.rb | 40 +++++++------ lib/recombee_api_client/version.rb | 2 +- spec/api/add_entity.rb | 2 +- spec/api/delete_entity.rb | 2 +- spec/api/delete_property.rb | 2 +- spec/api/list_entities_with_properties.rb | 22 +++++++ spec/api/list_items_spec.rb | 4 +- spec/api/list_users_spec.rb | 4 +- 33 files changed, 229 insertions(+), 89 deletions(-) create mode 100644 spec/api/list_entities_with_properties.rb diff --git a/lib/recombee_api_client.rb b/lib/recombee_api_client.rb index 79d6dad..121f536 100644 --- a/lib/recombee_api_client.rb +++ b/lib/recombee_api_client.rb @@ -18,6 +18,7 @@ class RecombeeClient include HTTParty BATCH_MAX_SIZE = 10000 + USER_AGENT = {'User-Agent' => 'recombee-ruby-api-client/1.4.0'} ## # - +account+ -> Name of your account at Recombee @@ -63,13 +64,15 @@ def send(request) private def put(request, uri, timeout) - response = self.class.put(uri, timeout: timeout) + response = self.class.put(uri, body: request.body_parameters.to_json, + headers: { 'Content-Type' => 'application/json' }.merge(USER_AGENT), + timeout: timeout) check_errors(response, request) response.body end def get(request, uri, timeout) - response = self.class.get(uri, timeout: timeout) + response = self.class.get(uri, timeout: timeout, headers: USER_AGENT) check_errors(response, request) JSON.parse(response.body) end @@ -77,7 +80,7 @@ def get(request, uri, timeout) def post(request, uri, timeout) # pass arguments in body response = self.class.post(uri, body: request.body_parameters.to_json, - headers: { 'Content-Type' => 'application/json' }, + headers: { 'Content-Type' => 'application/json' }.merge(USER_AGENT), timeout: timeout) check_errors(response, request) begin @@ -88,7 +91,7 @@ def post(request, uri, timeout) end def delete(request, uri, timeout) - response = self.class.delete(uri, timeout: timeout) + response = self.class.delete(uri, timeout: timeout, headers: USER_AGENT) check_errors(response, request) response.body end diff --git a/lib/recombee_api_client/api/add_bookmark.rb b/lib/recombee_api_client/api/add_bookmark.rb index 148f6fb..b203061 100644 --- a/lib/recombee_api_client/api/add_bookmark.rb +++ b/lib/recombee_api_client/api/add_bookmark.rb @@ -46,8 +46,8 @@ def body_parameters p = Hash.new p['userId'] = @user_id p['itemId'] = @item_id - p['timestamp'] = @optional['timestamp'] if @optional['timestamp'] - p['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] + p['timestamp'] = @optional['timestamp'] if @optional.include? 'timestamp' + p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate' p end diff --git a/lib/recombee_api_client/api/add_cart_addition.rb b/lib/recombee_api_client/api/add_cart_addition.rb index fc1978e..0a43985 100644 --- a/lib/recombee_api_client/api/add_cart_addition.rb +++ b/lib/recombee_api_client/api/add_cart_addition.rb @@ -46,8 +46,8 @@ def body_parameters p = Hash.new p['userId'] = @user_id p['itemId'] = @item_id - p['timestamp'] = @optional['timestamp'] if @optional['timestamp'] - p['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] + p['timestamp'] = @optional['timestamp'] if @optional.include? 'timestamp' + p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate' p end diff --git a/lib/recombee_api_client/api/add_detail_view.rb b/lib/recombee_api_client/api/add_detail_view.rb index ccaf892..a02295f 100644 --- a/lib/recombee_api_client/api/add_detail_view.rb +++ b/lib/recombee_api_client/api/add_detail_view.rb @@ -48,9 +48,9 @@ def body_parameters p = Hash.new p['userId'] = @user_id p['itemId'] = @item_id - p['timestamp'] = @optional['timestamp'] if @optional['timestamp'] - p['duration'] = @optional['duration'] if @optional['duration'] - p['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] + p['timestamp'] = @optional['timestamp'] if @optional.include? 'timestamp' + p['duration'] = @optional['duration'] if @optional.include? 'duration' + p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate' p end diff --git a/lib/recombee_api_client/api/add_purchase.rb b/lib/recombee_api_client/api/add_purchase.rb index c9cf34b..42ed9b8 100644 --- a/lib/recombee_api_client/api/add_purchase.rb +++ b/lib/recombee_api_client/api/add_purchase.rb @@ -46,8 +46,8 @@ def body_parameters p = Hash.new p['userId'] = @user_id p['itemId'] = @item_id - p['timestamp'] = @optional['timestamp'] if @optional['timestamp'] - p['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] + p['timestamp'] = @optional['timestamp'] if @optional.include? 'timestamp' + p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate' p end diff --git a/lib/recombee_api_client/api/add_rating.rb b/lib/recombee_api_client/api/add_rating.rb index c11b1d3..783c40a 100644 --- a/lib/recombee_api_client/api/add_rating.rb +++ b/lib/recombee_api_client/api/add_rating.rb @@ -49,8 +49,8 @@ def body_parameters p['userId'] = @user_id p['itemId'] = @item_id p['rating'] = @rating - p['timestamp'] = @optional['timestamp'] if @optional['timestamp'] - p['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] + p['timestamp'] = @optional['timestamp'] if @optional.include? 'timestamp' + p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate' p end diff --git a/lib/recombee_api_client/api/insert_to_group.rb b/lib/recombee_api_client/api/insert_to_group.rb index caa27c9..372436b 100644 --- a/lib/recombee_api_client/api/insert_to_group.rb +++ b/lib/recombee_api_client/api/insert_to_group.rb @@ -46,7 +46,7 @@ def body_parameters p = Hash.new p['itemType'] = @item_type p['itemId'] = @item_id - p['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] + p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate' p end diff --git a/lib/recombee_api_client/api/insert_to_series.rb b/lib/recombee_api_client/api/insert_to_series.rb index 8175419..21641f1 100644 --- a/lib/recombee_api_client/api/insert_to_series.rb +++ b/lib/recombee_api_client/api/insert_to_series.rb @@ -49,7 +49,7 @@ def body_parameters p['itemType'] = @item_type p['itemId'] = @item_id p['time'] = @time - p['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] + p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate' p end diff --git a/lib/recombee_api_client/api/item_based_recommendation.rb b/lib/recombee_api_client/api/item_based_recommendation.rb index 37bbf5c..0c124d8 100644 --- a/lib/recombee_api_client/api/item_based_recommendation.rb +++ b/lib/recombee_api_client/api/item_based_recommendation.rb @@ -9,14 +9,16 @@ module RecombeeApiClient ## #Recommends set of items that are somehow related to one given item, *X*. Typical scenario for using item-based recommendation is when user *A* is viewing *X*. Then you may display items to the user that he might be also interested in. Item-recommendation request gives you Top-N such items, optionally taking the target user *A* into account. # + # It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters. + # class ItemBasedRecommendation < ApiRequest - attr_reader :item_id, :count, :target_user_id, :user_impact, :filter, :booster, :allow_nonexistent, :cascade_create, :scenario, :return_properties, :included_properties, :diversity, :min_relevance, :rotation_rate, :rotation_time + attr_reader :item_id, :count, :target_user_id, :user_impact, :filter, :booster, :allow_nonexistent, :cascade_create, :scenario, :return_properties, :included_properties, :diversity, :min_relevance, :rotation_rate, :rotation_time, :expert_settings attr_accessor :timeout attr_accessor :ensure_https ## # * *Required arguments* - # - +item_id+ -> ID of the item recommendations for which are to be generated. + # - +item_id+ -> ID of the item for which the recommendations are to be generated. # - +count+ -> Number of items to be recommended (N for the top-N recommendation). # # * *Optional arguments (given as hash optional)* @@ -25,15 +27,18 @@ class ItemBasedRecommendation < ApiRequest #Specifying the *targetUserId* is beneficial because: # #* It makes the recommendations personalized - #* Allows calculations of Actions and Conversions in the graphical user interface, as Recombee can pair the user who got recommendations and who afterwards viewed/purchased an item. + #* Allows the calculation of Actions and Conversions in the graphical user interface, + # as Recombee can pair the user who got recommendations and who afterwards viewed/purchased an item. + # + #For the above reasons, we encourage you to set the *targetUserId* even for anonymous/unregistered users (i.e. use their session ID). # - # - +userImpact+ -> If *targetUserId* parameter is present, the recommendations are biased towards the user given. Using *userImpact*, you may control this bias. For an extreme case of `userImpact=0.0`, the interactions made by the user are not taken into account at all (with the exception of history-based blacklisting), for `userImpact=1.0`, you'll get user-based recommendation. The default value is `0.1` + # - +userImpact+ -> If *targetUserId* parameter is present, the recommendations are biased towards the user given. Using *userImpact*, you may control this bias. For an extreme case of `userImpact=0.0`, the interactions made by the user are not taken into account at all (with the exception of history-based blacklisting), for `userImpact=1.0`, you'll get user-based recommendation. The default value is `0`. # # - +filter+ -> Boolean-returning [ReQL](https://docs.recombee.com/reql.html) expression which allows you to filter recommended items based on the values of their attributes. # - +booster+ -> Number-returning [ReQL](https://docs.recombee.com/reql.html) expression which allows you to boost recommendation rate of some items based on the values of their attributes. # - +allowNonexistent+ -> Instead of causing HTTP 404 error, returns some (non-personalized) recommendations if either item of given *itemId* or user of given *targetUserId* does not exist in the database. It creates neither of the missing entities in the database. # - +cascadeCreate+ -> If item of given *itemId* or user of given *targetUserId* doesn't exist in the database, it creates the missing enity/entities and returns some (non-personalized) recommendations. This allows for example rotations in the following recommendations for the user of given *targetUserId*, as the user will be already known to the system. - # - +scenario+ -> Scenario defines a particular application of recommendations. It can be for example "homepage" or "cart". The AI which optimizes models in order to get the best results may optimize different scenarios separately, or even use different models in each of the scenarios. + # - +scenario+ -> Scenario defines a particular application of recommendations. It can be for example "homepage", "cart" or "emailing". You can see each scenario in the UI separately, so you can check how well each application performs. The AI which optimizes models in order to get the best results may optimize different scenarios separately, or even use different models in each of the scenarios. # - +returnProperties+ -> With `returnProperties=true`, property values of the recommended items are returned along with their IDs in a JSON dictionary. The acquired property values can be used for easy displaying of the recommended items to the user. # #Example response: @@ -80,7 +85,9 @@ class ItemBasedRecommendation < ApiRequest # # - +rotationRate+ -> **Expert option** If the *targetUserId* is provided: If your users browse the system in real-time, it may easily happen that you wish to offer them recommendations multiple times. Here comes the question: how much should the recommendations change? Should they remain the same, or should they rotate? Recombee API allows you to control this per-request in backward fashion. You may penalize an item for being recommended in the near past. For the specific user, `rotationRate=1` means maximal rotation, `rotationRate=0` means absolutely no rotation. You may also use, for example `rotationRate=0.2` for only slight rotation of recommended items. # - # - +rotationTime+ -> **Expert option** If the *targetUserId* is provided: Taking *rotationRate* into account, specifies how long time it takes to an item to fully recover from the penalization. For example, `rotationTime=7200.0` means that items recommended more than 2 hours ago are definitely not penalized anymore. Currently, the penalization is linear, so for `rotationTime=7200.0`, an item is still penalized by `0.5` to the user after 1 hour. + # - +rotationTime+ -> **Expert option** If the *targetUserId* is provided: Taking *rotationRate* into account, specifies how long time it takes to an item to recover from the penalization. For example, `rotationTime=7200.0` means that items recommended less than 2 hours ago are penalized. + # + # - +expertSettings+ -> Dictionary of custom options. # # def initialize(item_id, count, optional = {}) @@ -99,22 +106,38 @@ def initialize(item_id, count, optional = {}) @min_relevance = optional['minRelevance'] @rotation_rate = optional['rotationRate'] @rotation_time = optional['rotationTime'] + @expert_settings = optional['expertSettings'] @optional = optional @timeout = 3000 @ensure_https = false @optional.each do |par, _| - fail UnknownOptionalParameter.new(par) unless ["targetUserId","userImpact","filter","booster","allowNonexistent","cascadeCreate","scenario","returnProperties","includedProperties","diversity","minRelevance","rotationRate","rotationTime"].include? par + fail UnknownOptionalParameter.new(par) unless ["targetUserId","userImpact","filter","booster","allowNonexistent","cascadeCreate","scenario","returnProperties","includedProperties","diversity","minRelevance","rotationRate","rotationTime","expertSettings"].include? par end end # HTTP method def method - :get + :post end # Values of body parameters as a Hash def body_parameters p = Hash.new + p['count'] = @count + p['targetUserId'] = @optional['targetUserId'] if @optional.include? 'targetUserId' + p['userImpact'] = @optional['userImpact'] if @optional.include? 'userImpact' + p['filter'] = @optional['filter'] if @optional.include? 'filter' + p['booster'] = @optional['booster'] if @optional.include? 'booster' + p['allowNonexistent'] = @optional['allowNonexistent'] if @optional.include? 'allowNonexistent' + p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate' + p['scenario'] = @optional['scenario'] if @optional.include? 'scenario' + p['returnProperties'] = @optional['returnProperties'] if @optional.include? 'returnProperties' + p['includedProperties'] = @optional['includedProperties'] if @optional.include? 'includedProperties' + p['diversity'] = @optional['diversity'] if @optional.include? 'diversity' + p['minRelevance'] = @optional['minRelevance'] if @optional.include? 'minRelevance' + p['rotationRate'] = @optional['rotationRate'] if @optional.include? 'rotationRate' + p['rotationTime'] = @optional['rotationTime'] if @optional.include? 'rotationTime' + p['expertSettings'] = @optional['expertSettings'] if @optional.include? 'expertSettings' p end @@ -122,20 +145,6 @@ def body_parameters # name of parameter => value of the parameter def query_parameters params = {} - params['count'] = @count - params['targetUserId'] = @optional['targetUserId'] if @optional['targetUserId'] - params['userImpact'] = @optional['userImpact'] if @optional['userImpact'] - params['filter'] = @optional['filter'] if @optional['filter'] - params['booster'] = @optional['booster'] if @optional['booster'] - params['allowNonexistent'] = @optional['allowNonexistent'] if @optional['allowNonexistent'] - params['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] - params['scenario'] = @optional['scenario'] if @optional['scenario'] - params['returnProperties'] = @optional['returnProperties'] if @optional['returnProperties'] - params['includedProperties'] = @optional['includedProperties'] if @optional['includedProperties'] - params['diversity'] = @optional['diversity'] if @optional['diversity'] - params['minRelevance'] = @optional['minRelevance'] if @optional['minRelevance'] - params['rotationRate'] = @optional['rotationRate'] if @optional['rotationRate'] - params['rotationTime'] = @optional['rotationTime'] if @optional['rotationTime'] params end diff --git a/lib/recombee_api_client/api/list_groups.rb b/lib/recombee_api_client/api/list_groups.rb index 302e0b5..b5fbf80 100644 --- a/lib/recombee_api_client/api/list_groups.rb +++ b/lib/recombee_api_client/api/list_groups.rb @@ -16,7 +16,7 @@ class ListGroups < ApiRequest ## # def initialize() - @timeout = 30000 + @timeout = 239000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_item_bookmarks.rb b/lib/recombee_api_client/api/list_item_bookmarks.rb index 3e8797a..12d50dd 100644 --- a/lib/recombee_api_client/api/list_item_bookmarks.rb +++ b/lib/recombee_api_client/api/list_item_bookmarks.rb @@ -20,7 +20,7 @@ class ListItemBookmarks < ApiRequest # def initialize(item_id) @item_id = item_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_item_cart_additions.rb b/lib/recombee_api_client/api/list_item_cart_additions.rb index 98f342e..165aa6a 100644 --- a/lib/recombee_api_client/api/list_item_cart_additions.rb +++ b/lib/recombee_api_client/api/list_item_cart_additions.rb @@ -20,7 +20,7 @@ class ListItemCartAdditions < ApiRequest # def initialize(item_id) @item_id = item_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_item_detail_views.rb b/lib/recombee_api_client/api/list_item_detail_views.rb index 225886d..b1e5e15 100644 --- a/lib/recombee_api_client/api/list_item_detail_views.rb +++ b/lib/recombee_api_client/api/list_item_detail_views.rb @@ -20,7 +20,7 @@ class ListItemDetailViews < ApiRequest # def initialize(item_id) @item_id = item_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_item_purchases.rb b/lib/recombee_api_client/api/list_item_purchases.rb index dc9f299..dc04cfe 100644 --- a/lib/recombee_api_client/api/list_item_purchases.rb +++ b/lib/recombee_api_client/api/list_item_purchases.rb @@ -20,7 +20,7 @@ class ListItemPurchases < ApiRequest # def initialize(item_id) @item_id = item_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_item_ratings.rb b/lib/recombee_api_client/api/list_item_ratings.rb index c1696d2..74843b1 100644 --- a/lib/recombee_api_client/api/list_item_ratings.rb +++ b/lib/recombee_api_client/api/list_item_ratings.rb @@ -20,7 +20,7 @@ class ListItemRatings < ApiRequest # def initialize(item_id) @item_id = item_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_items.rb b/lib/recombee_api_client/api/list_items.rb index 69db510..d4c38d5 100644 --- a/lib/recombee_api_client/api/list_items.rb +++ b/lib/recombee_api_client/api/list_items.rb @@ -9,7 +9,7 @@ module RecombeeApiClient ## #Gets a list of IDs of items currently present in the catalog. class ListItems < ApiRequest - attr_reader :filter + attr_reader :filter, :count, :offset, :return_properties, :included_properties attr_accessor :timeout attr_accessor :ensure_https @@ -17,14 +17,60 @@ class ListItems < ApiRequest # # * *Optional arguments (given as hash optional)* # - +filter+ -> Boolean-returning [ReQL](https://docs.recombee.com/reql.html) expression, which allows you to filter items to be listed. Only the items for which the expression is *true* will be returned. + # - +count+ -> The number of items to be listed. + # - +offset+ -> Specifies the number of items to skip (ordered by `itemId`). + # - +returnProperties+ -> With `returnProperties=true`, property values of the listed items are returned along with their IDs in a JSON dictionary. + # + #Example response: + #``` + # [ + # { + # "itemId": "tv-178", + # "description": "4K TV with 3D feature", + # "categories": ["Electronics", "Televisions"], + # "price": 342, + # "url": "myshop.com/tv-178" + # }, + # { + # "itemId": "mixer-42", + # "description": "Stainless Steel Mixer", + # "categories": ["Home & Kitchen"], + # "price": 39, + # "url": "myshop.com/mixer-42" + # } + # ] + #``` + # + # - +includedProperties+ -> Allows to specify, which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. + # + #Example response for `includedProperties=description,price`: + #``` + # [ + # { + # "itemId": "tv-178", + # "description": "4K TV with 3D feature", + # "price": 342 + # }, + # { + # "itemId": "mixer-42", + # "description": "Stainless Steel Mixer", + # "price": 39 + # } + # ] + #``` + # # def initialize(optional = {}) @filter = optional['filter'] + @count = optional['count'] + @offset = optional['offset'] + @return_properties = optional['returnProperties'] + @included_properties = optional['includedProperties'] @optional = optional - @timeout = 30000 + @timeout = 600000 @ensure_https = false @optional.each do |par, _| - fail UnknownOptionalParameter.new(par) unless ["filter"].include? par + fail UnknownOptionalParameter.new(par) unless ["filter","count","offset","returnProperties","includedProperties"].include? par end end @@ -44,6 +90,10 @@ def body_parameters def query_parameters params = {} params['filter'] = @optional['filter'] if @optional['filter'] + params['count'] = @optional['count'] if @optional['count'] + params['offset'] = @optional['offset'] if @optional['offset'] + params['returnProperties'] = @optional['returnProperties'] if @optional['returnProperties'] + params['includedProperties'] = @optional['includedProperties'] if @optional['includedProperties'] params end diff --git a/lib/recombee_api_client/api/list_series.rb b/lib/recombee_api_client/api/list_series.rb index f125f33..54bcd21 100644 --- a/lib/recombee_api_client/api/list_series.rb +++ b/lib/recombee_api_client/api/list_series.rb @@ -16,7 +16,7 @@ class ListSeries < ApiRequest ## # def initialize() - @timeout = 30000 + @timeout = 239000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_user_bookmarks.rb b/lib/recombee_api_client/api/list_user_bookmarks.rb index 7ec0b26..e513732 100644 --- a/lib/recombee_api_client/api/list_user_bookmarks.rb +++ b/lib/recombee_api_client/api/list_user_bookmarks.rb @@ -19,7 +19,7 @@ class ListUserBookmarks < ApiRequest # def initialize(user_id) @user_id = user_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_user_cart_additions.rb b/lib/recombee_api_client/api/list_user_cart_additions.rb index 38997fe..7e593e5 100644 --- a/lib/recombee_api_client/api/list_user_cart_additions.rb +++ b/lib/recombee_api_client/api/list_user_cart_additions.rb @@ -19,7 +19,7 @@ class ListUserCartAdditions < ApiRequest # def initialize(user_id) @user_id = user_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_user_detail_views.rb b/lib/recombee_api_client/api/list_user_detail_views.rb index 3e9d674..1845836 100644 --- a/lib/recombee_api_client/api/list_user_detail_views.rb +++ b/lib/recombee_api_client/api/list_user_detail_views.rb @@ -19,7 +19,7 @@ class ListUserDetailViews < ApiRequest # def initialize(user_id) @user_id = user_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_user_purchases.rb b/lib/recombee_api_client/api/list_user_purchases.rb index c5737ba..7d544a1 100644 --- a/lib/recombee_api_client/api/list_user_purchases.rb +++ b/lib/recombee_api_client/api/list_user_purchases.rb @@ -19,7 +19,7 @@ class ListUserPurchases < ApiRequest # def initialize(user_id) @user_id = user_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_user_ratings.rb b/lib/recombee_api_client/api/list_user_ratings.rb index 9887eb9..4dd063c 100644 --- a/lib/recombee_api_client/api/list_user_ratings.rb +++ b/lib/recombee_api_client/api/list_user_ratings.rb @@ -19,7 +19,7 @@ class ListUserRatings < ApiRequest # def initialize(user_id) @user_id = user_id - @timeout = 1000 + @timeout = 100000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/list_users.rb b/lib/recombee_api_client/api/list_users.rb index f0e7444..ba9047f 100644 --- a/lib/recombee_api_client/api/list_users.rb +++ b/lib/recombee_api_client/api/list_users.rb @@ -9,15 +9,63 @@ module RecombeeApiClient ## #Gets a list of IDs of users currently present in the catalog. class ListUsers < ApiRequest - + attr_reader :filter, :count, :offset, :return_properties, :included_properties attr_accessor :timeout attr_accessor :ensure_https ## # - def initialize() - @timeout = 30000 + # * *Optional arguments (given as hash optional)* + # - +filter+ -> Boolean-returning [ReQL](https://docs.recombee.com/reql.html) expression, which allows you to filter users to be listed. Only the users for which the expression is *true* will be returned. + # - +count+ -> The number of users to be listed. + # - +offset+ -> Specifies the number of users to skip (ordered by `userId`). + # - +returnProperties+ -> With `returnProperties=true`, property values of the listed users are returned along with their IDs in a JSON dictionary. + # + #Example response: + #``` + # [ + # { + # "userId": "user-81", + # "country": "US", + # "sex": "M" + # }, + # { + # "userId": "user-314", + # "country": "CAN", + # "sex": "F" + # } + # ] + #``` + # + # - +includedProperties+ -> Allows to specify, which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. + # + #Example response for `includedProperties=country`: + #``` + # [ + # { + # "userId": "user-81", + # "country": "US" + # }, + # { + # "userId": "user-314", + # "country": "CAN" + # } + # ] + #``` + # + # + def initialize(optional = {}) + @filter = optional['filter'] + @count = optional['count'] + @offset = optional['offset'] + @return_properties = optional['returnProperties'] + @included_properties = optional['includedProperties'] + @optional = optional + @timeout = 239000 @ensure_https = false + @optional.each do |par, _| + fail UnknownOptionalParameter.new(par) unless ["filter","count","offset","returnProperties","includedProperties"].include? par + end end # HTTP method @@ -35,6 +83,11 @@ def body_parameters # name of parameter => value of the parameter def query_parameters params = {} + params['filter'] = @optional['filter'] if @optional['filter'] + params['count'] = @optional['count'] if @optional['count'] + params['offset'] = @optional['offset'] if @optional['offset'] + params['returnProperties'] = @optional['returnProperties'] if @optional['returnProperties'] + params['includedProperties'] = @optional['includedProperties'] if @optional['includedProperties'] params end diff --git a/lib/recombee_api_client/api/merge_users.rb b/lib/recombee_api_client/api/merge_users.rb index 9eac1d3..2efc7a2 100644 --- a/lib/recombee_api_client/api/merge_users.rb +++ b/lib/recombee_api_client/api/merge_users.rb @@ -13,7 +13,7 @@ module RecombeeApiClient #Merging happens between two users referred to as the *target* and the *source*. After the merge, all the interactions of the source user are attributed to the target user, and the source user is **deleted** unless special parameter `keepSourceUser` is set `true`. # class MergeUsers < ApiRequest - attr_reader :target_user_id, :source_user_id, :keep_source_user, :cascade_create + attr_reader :target_user_id, :source_user_id, :cascade_create attr_accessor :timeout attr_accessor :ensure_https @@ -23,19 +23,17 @@ class MergeUsers < ApiRequest # - +source_user_id+ -> ID of the target user. # # * *Optional arguments (given as hash optional)* - # - +keepSourceUser+ -> If true, the source user will not be deleted, but also kept in the database. # - +cascadeCreate+ -> Sets whether the user *targetUserId* should be created if not present in the database. # def initialize(target_user_id, source_user_id, optional = {}) @target_user_id = target_user_id @source_user_id = source_user_id - @keep_source_user = optional['keepSourceUser'] @cascade_create = optional['cascadeCreate'] @optional = optional - @timeout = 1000 + @timeout = 10000 @ensure_https = false @optional.each do |par, _| - fail UnknownOptionalParameter.new(par) unless ["keepSourceUser","cascadeCreate"].include? par + fail UnknownOptionalParameter.new(par) unless ["cascadeCreate"].include? par end end @@ -54,7 +52,6 @@ def body_parameters # name of parameter => value of the parameter def query_parameters params = {} - params['keepSourceUser'] = @optional['keepSourceUser'] if @optional['keepSourceUser'] params['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] params end diff --git a/lib/recombee_api_client/api/reset_database.rb b/lib/recombee_api_client/api/reset_database.rb index 3aca2bf..1760f7e 100644 --- a/lib/recombee_api_client/api/reset_database.rb +++ b/lib/recombee_api_client/api/reset_database.rb @@ -17,7 +17,7 @@ class ResetDatabase < ApiRequest ## # def initialize() - @timeout = 20000 + @timeout = 239000 @ensure_https = false end diff --git a/lib/recombee_api_client/api/user_based_recommendation.rb b/lib/recombee_api_client/api/user_based_recommendation.rb index f186a02..14b1106 100644 --- a/lib/recombee_api_client/api/user_based_recommendation.rb +++ b/lib/recombee_api_client/api/user_based_recommendation.rb @@ -9,8 +9,10 @@ module RecombeeApiClient ## #Based on user's past interactions (purchases, ratings, etc.) with the items, recommends top-N items that are most likely to be of high value for a given user. # + #It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters. + # class UserBasedRecommendation < ApiRequest - attr_reader :user_id, :count, :filter, :booster, :allow_nonexistent, :cascade_create, :scenario, :return_properties, :included_properties, :diversity, :min_relevance, :rotation_rate, :rotation_time + attr_reader :user_id, :count, :filter, :booster, :allow_nonexistent, :cascade_create, :scenario, :return_properties, :included_properties, :diversity, :min_relevance, :rotation_rate, :rotation_time, :expert_settings attr_accessor :timeout attr_accessor :ensure_https @@ -24,7 +26,7 @@ class UserBasedRecommendation < ApiRequest # - +booster+ -> Number-returning [ReQL](https://docs.recombee.com/reql.html) expression which allows you to boost recommendation rate of some items based on the values of their attributes. # - +allowNonexistent+ -> If the user does not exist in the database, returns a list of non-personalized recommendations instead of causing HTTP 404 error. It doesn't create the user in the database. # - +cascadeCreate+ -> If the user does not exist in the database, returns a list of non-personalized recommendations and creates the user in the database. This allows for example rotations in the following recommendations for that user, as the user will be already known to the system. - # - +scenario+ -> Scenario defines a particular application of recommendations. It can be for example "homepage" or "cart". The AI which optimizes models in order to get the best results may optimize different scenarios separately, or even use different models in each of the scenarios. + # - +scenario+ -> Scenario defines a particular application of recommendations. It can be for example "homepage", "cart" or "emailing". You can see each scenario in the UI separately, so you can check how well each application performs. The AI which optimizes models in order to get the best results may optimize different scenarios separately, or even use different models in each of the scenarios. # - +returnProperties+ -> With `returnProperties=true`, property values of the recommended items are returned along with their IDs in a JSON dictionary. The acquired property values can be used for easy displaying of the recommended items to the user. # #Example response: @@ -71,7 +73,9 @@ class UserBasedRecommendation < ApiRequest # # - +rotationRate+ -> **Expert option** If your users browse the system in real-time, it may easily happen that you wish to offer them recommendations multiple times. Here comes the question: how much should the recommendations change? Should they remain the same, or should they rotate? Recombee API allows you to control this per-request in backward fashion. You may penalize an item for being recommended in the near past. For the specific user, `rotationRate=1` means maximal rotation, `rotationRate=0` means absolutely no rotation. You may also use, for example `rotationRate=0.2` for only slight rotation of recommended items. # - # - +rotationTime+ -> **Expert option** Taking *rotationRate* into account, specifies how long time it takes to an item to fully recover from the penalization. For example, `rotationTime=7200.0` means that items recommended more than 2 hours ago are definitely not penalized anymore. Currently, the penalization is linear, so for `rotationTime=7200.0`, an item is still penalized by `0.5` to the user after 1 hour. + # - +rotationTime+ -> **Expert option** Taking *rotationRate* into account, specifies how long time it takes to an item to recover from the penalization. For example, `rotationTime=7200.0` means that items recommended less than 2 hours ago are penalized. + # + # - +expertSettings+ -> Dictionary of custom options. # # def initialize(user_id, count, optional = {}) @@ -88,22 +92,36 @@ def initialize(user_id, count, optional = {}) @min_relevance = optional['minRelevance'] @rotation_rate = optional['rotationRate'] @rotation_time = optional['rotationTime'] + @expert_settings = optional['expertSettings'] @optional = optional @timeout = 3000 @ensure_https = false @optional.each do |par, _| - fail UnknownOptionalParameter.new(par) unless ["filter","booster","allowNonexistent","cascadeCreate","scenario","returnProperties","includedProperties","diversity","minRelevance","rotationRate","rotationTime"].include? par + fail UnknownOptionalParameter.new(par) unless ["filter","booster","allowNonexistent","cascadeCreate","scenario","returnProperties","includedProperties","diversity","minRelevance","rotationRate","rotationTime","expertSettings"].include? par end end # HTTP method def method - :get + :post end # Values of body parameters as a Hash def body_parameters p = Hash.new + p['count'] = @count + p['filter'] = @optional['filter'] if @optional.include? 'filter' + p['booster'] = @optional['booster'] if @optional.include? 'booster' + p['allowNonexistent'] = @optional['allowNonexistent'] if @optional.include? 'allowNonexistent' + p['cascadeCreate'] = @optional['cascadeCreate'] if @optional.include? 'cascadeCreate' + p['scenario'] = @optional['scenario'] if @optional.include? 'scenario' + p['returnProperties'] = @optional['returnProperties'] if @optional.include? 'returnProperties' + p['includedProperties'] = @optional['includedProperties'] if @optional.include? 'includedProperties' + p['diversity'] = @optional['diversity'] if @optional.include? 'diversity' + p['minRelevance'] = @optional['minRelevance'] if @optional.include? 'minRelevance' + p['rotationRate'] = @optional['rotationRate'] if @optional.include? 'rotationRate' + p['rotationTime'] = @optional['rotationTime'] if @optional.include? 'rotationTime' + p['expertSettings'] = @optional['expertSettings'] if @optional.include? 'expertSettings' p end @@ -111,18 +129,6 @@ def body_parameters # name of parameter => value of the parameter def query_parameters params = {} - params['count'] = @count - params['filter'] = @optional['filter'] if @optional['filter'] - params['booster'] = @optional['booster'] if @optional['booster'] - params['allowNonexistent'] = @optional['allowNonexistent'] if @optional['allowNonexistent'] - params['cascadeCreate'] = @optional['cascadeCreate'] if @optional['cascadeCreate'] - params['scenario'] = @optional['scenario'] if @optional['scenario'] - params['returnProperties'] = @optional['returnProperties'] if @optional['returnProperties'] - params['includedProperties'] = @optional['includedProperties'] if @optional['includedProperties'] - params['diversity'] = @optional['diversity'] if @optional['diversity'] - params['minRelevance'] = @optional['minRelevance'] if @optional['minRelevance'] - params['rotationRate'] = @optional['rotationRate'] if @optional['rotationRate'] - params['rotationTime'] = @optional['rotationTime'] if @optional['rotationTime'] params end diff --git a/lib/recombee_api_client/version.rb b/lib/recombee_api_client/version.rb index 0563e71..b15b256 100644 --- a/lib/recombee_api_client/version.rb +++ b/lib/recombee_api_client/version.rb @@ -1,3 +1,3 @@ module RecombeeApiClient - VERSION = '1.3.1' + VERSION = '1.4.0' end diff --git a/spec/api/add_entity.rb b/spec/api/add_entity.rb index 4373706..c97cdfb 100644 --- a/spec/api/add_entity.rb +++ b/spec/api/add_entity.rb @@ -13,7 +13,7 @@ end it 'fails with invalid entity id' do - req = described_class.new('not_valid_id-*.?!') + req = described_class.new('...not_valid...') expect { @client.send(req) }.to raise_exception { |exception| expect(exception).to be_a(RecombeeApiClient::ResponseError) expect(exception.status_code).to eq 400 diff --git a/spec/api/delete_entity.rb b/spec/api/delete_entity.rb index e037ab2..c1d3be1 100644 --- a/spec/api/delete_entity.rb +++ b/spec/api/delete_entity.rb @@ -17,7 +17,7 @@ end it 'fails with invalid entity id' do - req = described_class.new('not_valid_id-*.?!') + req = described_class.new('...not_valid...') expect { @client.send(req) }.to raise_exception { |exception| expect(exception).to be_a(RecombeeApiClient::ResponseError) expect(exception.status_code).to eq 400 diff --git a/spec/api/delete_property.rb b/spec/api/delete_property.rb index d045373..376d5be 100644 --- a/spec/api/delete_property.rb +++ b/spec/api/delete_property.rb @@ -17,7 +17,7 @@ end it 'fails with invalid property' do - req = described_class.new('not_valid_id-*.?!') + req = described_class.new('...not_valid...') expect { @client.send(req) }.to raise_exception { |exception| expect(exception).to be_a(RecombeeApiClient::ResponseError) expect(exception.status_code).to eq 400 diff --git a/spec/api/list_entities_with_properties.rb b/spec/api/list_entities_with_properties.rb new file mode 100644 index 0000000..e212d06 --- /dev/null +++ b/spec/api/list_entities_with_properties.rb @@ -0,0 +1,22 @@ +# +# This file is auto-generated, do not edit +# + +require 'spec_helper' +require_relative 'set_environment' +shared_examples 'list entities with properties' do +include_context 'set environment' + + it 'lists entities' do + req = described_class.new() + resp = @client.send(req) + expect(resp).to eq ['entity_id'] + end + + it 'return properties' do + req = described_class.new() + resp = @client.send(req) + expect(resp.size).to eq 1 + end + +end diff --git a/spec/api/list_items_spec.rb b/spec/api/list_items_spec.rb index 39a3383..116686a 100644 --- a/spec/api/list_items_spec.rb +++ b/spec/api/list_items_spec.rb @@ -3,8 +3,8 @@ # require 'spec_helper' -require_relative "list_entities" +require_relative "list_entities_with_properties" describe RecombeeApiClient::ListItems do - it_behaves_like "list entities" + it_behaves_like "list entities with properties" end \ No newline at end of file diff --git a/spec/api/list_users_spec.rb b/spec/api/list_users_spec.rb index e5458a2..b88d983 100644 --- a/spec/api/list_users_spec.rb +++ b/spec/api/list_users_spec.rb @@ -3,8 +3,8 @@ # require 'spec_helper' -require_relative "list_entities" +require_relative "list_entities_with_properties" describe RecombeeApiClient::ListUsers do - it_behaves_like "list entities" + it_behaves_like "list entities with properties" end \ No newline at end of file