Class: DirectedEdge::Item

Inherits:
Resource show all
Defined in:
lib/directed_edge.rb

Overview

Represents an item in a Directed Edge database. Items can be products, pages or users, for instance. Usually items groups are differentiated from one another by a set of tags that are provided.

For instance, a user in the Directed Edge database could be modeled as:

user = DirectedEdge::Item.new(database, 'user_1')
user.add_tag('user')
user.save

Similarly a product could be:

product = DirectedEdge::Item.new(database, 'product_1')
product.add_tag('product')
product['price'] = '$42'
product.save

Note here that items have tags and properties. Tags are a free-form set of text identifiers that can be associated with an item, e.g. “user”, “product”, “page”, “science fiction”, etc.

Properties are a set of key-value pairs associated with the item. For example, product['price'] = '$42', or user['first name'] = 'Bob'.

If we wanted to link the user to the product, for instance, indicating that the user had purchased the product we can use:

user.link_to(product)
user.save

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(database, id) ⇒ Item

Creates a handle to an item in the DirectedEdge database which may be manipulated locally and then saved back to the database by calling save.



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/directed_edge.rb', line 350

def initialize(database, id)
  super(database.resource[URI.escape(id, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))])

  @database = database
  @id = id
  @links = CollectionHash.new(Hash)
  @tags = Set.new
  @preselected = []
  @blacklisted = Set.new
  @properties = {}

  @links_to_remove = CollectionHash.new(Set)
  @tags_to_remove = Set.new
  @preselected_to_remove = Set.new
  @blacklisted_to_remove = Set.new
  @properties_to_remove = Set.new
  @cached = false
end

Instance Attribute Details

#idObject (readonly)

The unique item identifier used by the database and specified in the item’s constructor.



345
346
347
# File 'lib/directed_edge.rb', line 345

def id
  @id
end

Instance Method Details

#==(other) ⇒ Boolean

can either be a string or an item object.

Returns:

  • (Boolean)

    True if the other item has the same ID. The item given



372
373
374
375
376
377
378
# File 'lib/directed_edge.rb', line 372

def ==(other)
  if other.is_a?(Item)
    other.id == id
  else
    other.to_s == id
  end
end

#[](property_name) ⇒ String

Fetches properties of the item.

Returns:

  • (String)

    The property for this item.



506
507
508
509
# File 'lib/directed_edge.rb', line 506

def [](property_name)
  read
  @properties[property_name]
end

#[]=(property_name, value) ⇒ Item

Assigns value to the given property_name.

This will not be written back to the database until save is called.

Returns:



517
518
519
520
521
# File 'lib/directed_edge.rb', line 517

def []=(property_name, value)
  @properties_to_remove.delete(property_name)
  @properties[property_name] = value
  self
end

#add_blacklisted(item) ⇒ String

Adds a blacklisted item that should never be shown as recommended for this item.

Parameters:

  • item (String)

    The ID (or an Item instance) of the item that should be blacklisted.

Returns:

  • (String)

    The ID just blacklisted.



664
665
666
667
668
# File 'lib/directed_edge.rb', line 664

def add_blacklisted(item)
  @blacklisted_to_remove.delete(item.to_s)
  @blacklisted.add(item.to_s)
  item
end

#add_preselected(item) ⇒ String

Adds a hand-picked recommendation for this item.

Note that preselected recommendations are weighted by the order that they are added, i.e. the first preselected item added will be the first one shown.

Parameters:

  • item (String)

    The ID (or an Item instance) of the item that should be always returned as a recommendation for this item.

Returns:

  • (String)

    The ID just added.



637
638
639
640
641
# File 'lib/directed_edge.rb', line 637

def add_preselected(item)
  @preselected_to_remove.delete(item.to_s)
  @preselected.push(item.to_s)
  item
end

#add_tag(tag) ⇒ String

Adds a tag to this item.

The changes will not be reflected in the database until save is called.

Parameters:

  • tag (String)

    The tag to be added to this item’s tag set.

Returns:

  • (String)

    The tag just added.



608
609
610
611
612
# File 'lib/directed_edge.rb', line 608

def add_tag(tag)
  @tags_to_remove.delete(tag)
  @tags.add(tag)
  tag
end

#blacklistedArray

An ordered list of blacklisted recommendations for this item.

Returns:

  • (Array)

    The items blacklisted from being recommended for this item.



488
489
490
491
# File 'lib/directed_edge.rb', line 488

def blacklisted
  read
  @blacklisted
end

#clear_property(property_name) ⇒ Item

Remove the given property_name.

Returns:



527
528
529
530
531
# File 'lib/directed_edge.rb', line 527

def clear_property(property_name)
  @properties_to_remove.add(property_name) unless @cached
  @properties.delete(property_name)
  self
end

#create(links = {}, tags = Set.new, properties = {}) ⇒ Object

Deprecated.

Use new / save instead.



388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/directed_edge.rb', line 388

def create(links={}, tags=Set.new, properties={})
  warn 'DirectedEdge::Item::create has been deprecated. Use new / save instead.'
  @links[''] = links
  @tags = tags
  @properties = properties

  # Here we pretend that it's cached since this is now the authoritative
  # copy of the values.

  @cached = true
  save
end

#destroyObject

Removes an item from the database, including deleting all links to and from this item.



536
537
538
539
# File 'lib/directed_edge.rb', line 536

def destroy
  @resource.delete
  nil
end

Creates a link from this item to other.

Weighted links are typically used to encode ratings. For instance, if a user has rated a given product that can be specified via:

user = DirectedEdge::Item(database, 'user_1')
product = DirectedEdge::Item(database, 'product_1') # preexisting item
user.link_to(product, 5)
user.save

Note that ‘other’ must exist in the database or must be saved before this item is saved. Otherwise the link will be ignored as the engine tries to detect ‘broken’ links that do not terminate at a valid item.

Parameters:

  • other (String)

    An identifier (or Item instance) for an item to be linked to.

  • weight (Integer) (defaults to: 0)

    A weight in the range of 1 to 10 for this link. If not specified (which is fine for most situations) an unweighted link will be created.

  • type (String) (defaults to: '')

    The link type to be used for this connection, or, the default untyped link. This could be, for example, purchase or rating.

Returns:

  • (String)

    The item ID just linked to

Raises:

  • (RangeError)


565
566
567
568
569
570
# File 'lib/directed_edge.rb', line 565

def link_to(other, weight=0, type='')
  raise RangeError if (weight < 0 || weight > 10)
  @links_to_remove[type.to_s].delete(other)
  @links[type.to_s][other.to_s] = weight
  other
end

Returns Items that are linked to from this item.

Parameters:

  • type (String) (defaults to: '')

    Only links for the specified link-type will be returned.

Returns:

  • (Set)

    Items that are linked to from this item.



463
464
465
466
# File 'lib/directed_edge.rb', line 463

def links(type='')
  read
  @links[type.to_s]
end

#nameString

Returns The item’s ID.

Returns:

  • (String)

    The item’s ID



382
383
384
# File 'lib/directed_edge.rb', line 382

def name
  @id
end

#preselectedArray

An ordered list of preselected recommendations for this item.

Returns:

  • (Array)

    The preselected recommendations for this item.



479
480
481
482
# File 'lib/directed_edge.rb', line 479

def preselected
  read
  @preselected
end

#propertiesHash

All properties for this item.

Returns:

  • (Hash)

    All of the properties for this item.



497
498
499
500
# File 'lib/directed_edge.rb', line 497

def properties
  read
  @properties
end

related and recommended are the two main methods for querying for recommendations with the Directed Edge API. Related is for similar items, e.g. “products like this product”, whereas recommended is for personalized recommendations, i.e. “We think you’d like…”

strongly recommended items first.

will be returned.

the web services API in the query string.

This will not reflect any unsaved changes to items.

Parameters:

  • tags (Set) (defaults to: Set.new)

    Only items which have at least one of the provided tags

  • options (Hash)

    A set of options which are passed directly on to

  • params (Hash) (defaults to: {})

    a customizable set of options

Options Hash (params):

  • :exclude_linked (Boolean) — default: false

    Exclude items which are linked directly from this item.

  • :max_results (Integer) — default: 20

    Only returns up to :max_results items.

  • :link_type_weight (Integer) — default: 1

    Here link_type should be replace with one of the actual link types in use in your database, i.e. :purchase_weight and specifies how strongly links of that type should be weighted related to other link types. For Instance if you wanted 20% ratings and 80% purchases you would specify: :purchases_weight => 8, :ratings_weight => 2

Returns:

  • (Array)

    List of item IDs recommeded for this item with the most

See Also:



752
753
754
755
756
757
758
759
760
761
# File 'lib/directed_edge.rb', line 752

def recommended(tags=Set.new, params={})
  normalize_params!(params)
  params['tags'] = tags.to_a.join(',')
  params.key?('excludeLinked') || params['excludeLinked'] = 'true'
  if with_properties?(params)
    property_hash_from_document(read_document('recommended', params), 'recommended')
  else
    list_from_document(read_document('recommended', params), 'recommended')
  end
end

related and recommended are the two main methods for querying for recommendations with the Directed Edge API. Related is for similar items, e.g. “products like this product”, whereas recommended is for personalized recommendations, i.e. “We think you’d like…”

related items first.

will be returned.

the web services API in the query string.

This will not reflect any unsaved changes to items.

Parameters:

  • tags (Set) (defaults to: Set.new)

    Only items which have at least one of the provided tags

  • options (Hash)

    A set of options which are passed directly on to

  • params (Hash) (defaults to: {})

    a customizable set of options

Options Hash (params):

  • :exclude_linked (Boolean) — default: false

    Exclude items which are linked directly from this item.

  • :max_results (Integer) — default: 20

    Only returns up to :max_results items.

  • :link_type_weight (Integer) — default: 1

    Here link_type should be replace with one of the actual link types in use in your database, i.e. :purchase_weight and specifies how strongly links of that type should be weighted related to other link types. For Instance if you wanted 20% ratings and 80% purchases you would specify: :purchases_weight => 8, :ratings_weight => 2

Returns:

  • (Array)

    List of item IDs related to this one with the most closely

See Also:



713
714
715
716
717
718
719
720
721
# File 'lib/directed_edge.rb', line 713

def related(tags=Set.new, params={})
  normalize_params!(params)
  params['tags'] = tags.to_a.join(',')
  if with_properties?(params)
    property_hash_from_document(read_document('related', params), 'related')
  else
    list_from_document(read_document('related', params), 'related')
  end
end

#reloadItem

Reloads (or loads) the item from the database. Any unsaved changes will will be discarded.

Returns:



440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
# File 'lib/directed_edge.rb', line 440

def reload
  @links.clear
  @tags.clear
  @preselected.clear
  @blacklisted.clear
  @properties.clear

  @links_to_remove.clear
  @tags_to_remove.clear
  @preselected_to_remove.clear
  @blacklisted_to_remove.clear
  @properties_to_remove.clear

  @cached = false
  read
  self
end

#remove_blacklisted(item) ⇒ String

Removes a blacklisted item.

Parameters:

  • item (String)

    The ID (or an Item instance) of the item that should be removed from the blacklist.

Returns:

  • (String)

    The ID just delisted.

See Also:

  • Item::add_blacklisted


678
679
680
681
682
# File 'lib/directed_edge.rb', line 678

def remove_blacklisted(item)
  @blacklisted_to_remove.add(item.to_s) unless @cached
  @blacklisted.delete(item.to_s)
  item
end

#remove_preselected(item) ⇒ String

Removes a hand-picked recommendation for this item.

Parameters:

  • item (String)

    The ID (or an Item instance) of the item that should be removed from the preselected list.

Returns:

  • (String)

    The ID just removed.

See Also:



651
652
653
654
655
# File 'lib/directed_edge.rb', line 651

def remove_preselected(item)
  @preselected_to_remove.add(item.to_s) unless @cached
  @preselected.delete(item.to_s)
  item
end

#remove_tag(tag) ⇒ String

Removes a tag from this item.

The changes will not be reflected in the database until save is called.

Parameters:

  • tag (String)

    The tag to be removed from this item’s set of tags.

Returns:

  • (String)

    The tag just removed.



621
622
623
624
625
# File 'lib/directed_edge.rb', line 621

def remove_tag(tag)
  @tags_to_remove.add(tag) unless @cached
  @tags.delete(tag)
  tag
end

#save(options = {}) ⇒ Item

Writes all changes to links, tags and properties back to the database and returns this item.

Returns:



406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/directed_edge.rb', line 406

def save(options={})
  if options[:overwrite] || @cached
    put(complete_document)
  else

    # The web services API allows to add or remove things incrementally.
    # Since we're not in the cached case, let's check to see which action(s)
    # are appropriate.

    put(complete_document, 'add')

    ### CHECKING LINKS_TO_REMOVE.EMPTY? ISN'T CORRECT ANYMORE

    if !@links_to_remove.empty? ||
        !@tags_to_remove.empty? ||
        !@preselected_to_remove.empty? ||
        !@blacklisted_to_remove.empty? ||
        !@properties_to_remove.empty?
      put(removal_document, 'remove')
      @links_to_remove.clear
      @tags_to_remove.clear
      @properties_to_remove.clear
      @preselected_to_remove.clear
      @blacklisted_to_remove.clear
    end
  end
  self
end

#tagsSet

Returns The tags for this item.

Returns:

  • (Set)

    The tags for this item.



470
471
472
473
# File 'lib/directed_edge.rb', line 470

def tags
  read
  @tags
end

#to_sString

Returns The ID of the item.

Returns:

  • (String)

    The ID of the item.



765
766
767
# File 'lib/directed_edge.rb', line 765

def to_s
  @id
end

#to_xmlString

usual document regalia, e.g. starting with <item> (used for exporting the item to a file)

Returns:

  • (String)

    An XML representation of the item as a string not including the



773
774
775
# File 'lib/directed_edge.rb', line 773

def to_xml
  insert_item(REXML::Document.new).to_s
end

Removes a relationship from this item to another item.

The changes will not be reflected in the database until save is called.

Parameters:

  • other (String)

    The ID (or Item instance) for an object to be unlinked.

Returns:

  • (String)

    The item ID just unlinked from.

See Also:



581
582
583
584
585
# File 'lib/directed_edge.rb', line 581

def unlink_from(other, type='')
  @links_to_remove[type.to_s].add(other.to_s) unless @cached
  @links[type.to_s].delete(other.to_s)
  other
end

#weight_for(other, type = '') ⇒ Integer

If there is a link for “other” then it returns the weight for the given item. Zero indicates that no weight is assigned.

Parameters:

  • other (String)

    The item being queried for.

  • type (String) (defaults to: '')

    The link type of the relationship.

Returns:

  • (Integer)

    The weight for a link from this item to the specified item, or nil if not found.



596
597
598
599
# File 'lib/directed_edge.rb', line 596

def weight_for(other, type='')
  read
  @links[type.to_s][other.to_s]
end