Question

This is basically a simple task, but I can't find a way how to perform a sort/order data in Mongomapper Model with keys that belongs from its association.

Like suppose I have two models :

class Product 
 include MongoMapper::Document

 key :name, String
 key :product_category_id, ObjectId

 belongs_to :product_category
end

class ProductCategory
 include MongoMapper::Document

 key :name, String, :required => true, :unique => true
end

All I want to do is simple get the data from 'Product' that sorted by its 'Product Category's Name'.. I've already tried :

Product.where(:name => /#{@keyword}/i).sort("product_category.name".to_sym)

but not working, and many others ways that perform an error in return :(...

Is anybody could help me to solve this ?? Really appreciate a lot...

Thanks

Regards, Ronny

Was it helpful?

Solution

As specified in your question, Product and ProductCategory are mapped to separate collections in MongoDB. As such, you cannot do a SQL join, sort, select, and unique. MongoDB will not access more than one collection for a normal query. You can sort the products in local memory, but this requires fetching both the products and their associated product_categories.

Products.all.sort{|a, b| a.product_category.name <=> b.product_category.name}

However, you can take advantage of embedding so that the data is all in one collection, and therefore easily sortable by MongoDB.

class Product
  include MongoMapper::Document

  key :name, String
  one :product_category
end

class ProductCategory
  include MongoMapper::EmbeddedDocument

  key :name, String
end

Note that ProductCategory is an EmbeddedDocument. The test below shows a MongoMapper sort clause by 'product_category.name'. Hope that this helps your understanding and progress.

test/unit/product_test.rb

require 'test_helper'

class ProductTest < ActiveSupport::TestCase
  def setup
    Product.delete_all
  end

  test "association sort" do
    Product.create(name: 'Act of Valor', product_category: ProductCategory.new(name: 'movie'))
    Product.create(name: 'Oliver Twist', product_category: ProductCategory.new(name: 'book'))
    assert_equal(2, Product.count)

    products_by_db_order = Product.all.to_a
    assert_equal(['Act of Valor', 'Oliver Twist'], products_by_db_order.map(&:name))
    p products_by_db_order.map(&:name)

    products_by_category_order = Product.sort('product_category.name').to_a
    assert_equal(['Oliver Twist', 'Act of Valor'], products_by_category_order.map(&:name))
    p products_by_category_order.map(&:name)
  end
end

output

Run options: --name=test_association_sort

# Running tests:

["Act of Valor", "Oliver Twist"]
["Oliver Twist", "Act of Valor"]
.

Finished tests in 0.042368s, 23.6027 tests/s, 70.8082 assertions/s.

1 tests, 3 assertions, 0 failures, 0 errors, 0 skips
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top