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.



342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/directed_edge.rb', line 342

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.



337
338
339
# File 'lib/directed_edge.rb', line 337

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



364
365
366
367
368
369
370
# File 'lib/directed_edge.rb', line 364

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.



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

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:



509
510
511
512
513
# File 'lib/directed_edge.rb', line 509

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.



656
657
658
659
660
# File 'lib/directed_edge.rb', line 656

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.



629
630
631
632
633
# File 'lib/directed_edge.rb', line 629

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.



600
601
602
603
604
# File 'lib/directed_edge.rb', line 600

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.



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

def blacklisted
  read
  @blacklisted
end

#clear_property(property_name) ⇒ Item

Remove the given property_name.

Returns:



519
520
521
522
523
# File 'lib/directed_edge.rb', line 519

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.



380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/directed_edge.rb', line 380

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.



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

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)


557
558
559
560
561
562
# File 'lib/directed_edge.rb', line 557

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.



455
456
457
458
# File 'lib/directed_edge.rb', line 455

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

#nameString

Returns The item’s ID.

Returns:

  • (String)

    The item’s ID



374
375
376
# File 'lib/directed_edge.rb', line 374

def name
  @id
end

#preselectedArray

An ordered list of preselected recommendations for this item.

Returns:

  • (Array)

    The preselected recommendations for this item.



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

def preselected
  read
  @preselected
end

#propertiesHash

All properties for this item.

Returns:

  • (Hash)

    All of the properties for this item.



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

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:



744
745
746
747
748
749
750
751
752
753
# File 'lib/directed_edge.rb', line 744

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:



705
706
707
708
709
710
711
712
713
# File 'lib/directed_edge.rb', line 705

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:



432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
# File 'lib/directed_edge.rb', line 432

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


670
671
672
673
674
# File 'lib/directed_edge.rb', line 670

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:



643
644
645
646
647
# File 'lib/directed_edge.rb', line 643

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.



613
614
615
616
617
# File 'lib/directed_edge.rb', line 613

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:



398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/directed_edge.rb', line 398

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.



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

def tags
  read
  @tags
end

#to_sString

Returns The ID of the item.

Returns:

  • (String)

    The ID of the item.



757
758
759
# File 'lib/directed_edge.rb', line 757

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



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

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:



573
574
575
576
577
# File 'lib/directed_edge.rb', line 573

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.



588
589
590
591
# File 'lib/directed_edge.rb', line 588

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