How do I do Mongoid 1:N:M with a field - mongoid

I'm trying to describe a 1:N M:1 relationship with the linking table containing an extra fields of info. Both table1 and table3 both have a lot of fields.
The existing table looks like this:
Table1 1:N Table2 M:1 Table3
somethings extra info otherthings
id table1_id id
table3_id
The table2.extra info is messing things up for me. How do I describe this in mongoid?
class Model1
include Mongoid::Document
field :somethings, :type => String
has_many_and_belongs_to :inbetween
end
class ModelInbetween
include Mongoid::Document
field :extra_info, :type => String
???
end
class Model2
include Mongoid::Document
field :otherthings, :type => String
has_many_and_belongs_to :inbetween
end

In Mongoid, has_many and belongs_to are used to express a 1:N relationship between two collections. has_many_and_belongs_to is only used for N:N relationships. See here for the official documentation. As far as I can tell, your tables should look like this:
class Model1
include Mongoid::Document
field :somethings, :type => String
has_many :modelInbetweens
end
class ModelInbetween
include Mongoid::Document
field :extra_info, :type => String
belongs_to :model1
belongs_to :model2
end
class Model2
include Mongoid::Document
field :otherthings, :type => String
has_many :modelinbetweens
end
Also, make sure to pay attention to whether the plural/singular form of the model should be used in defining the relationships.

Related

Solr store and search ordinal numbers with suffixes

Suppose I have to store student academic details like...
College name -- text field searchable
Student Class -- text field searchable
Subjects -- multivalue field , text field searchable
How do I store/handle "Student class" because student can search like this "students of class 4th" , "Students of class 4" , "student of class fourth"
How Can I handle these (4th, 4, fourth) variations? What are elegant ways to do so.
Thanks
Amit Aggarwal
One way to solve this problem is to use a field type that supports query time synonyms. Check out the "text_general" type in the example solr schema.
In practice you would add rows like this to the synonyms.txt file in your cores conf dir:
# numbers
1,1st,first
2,2nd,second
3,3rd,third
4,4th,fourth
Now, lets suppose you had a document such as:
{ "college":"Princeton", "class":"1", "subjects":["CS 101", "introduction to full text search"]}
You could then retrieve that document if you do a query such as:
class:first
In this example the search query is directed towards one field, which may or may not be what you want. If you need to target the search query with number synonym matching into multiple fields( ie, search query with no field specifier, just the search term), you could copy all those fields content into a single synonym searchable field (using copyField) such as content_synonyms and then run the query against this field by default.

Mongoid Search in embedded documents in optimized way

I have 2 documents Users and books
class User
embeds_many :books
end
class Book
embedded_in :user
end
I want to search for books on some conditions, Is there an efficient way to do that rather than loop on all users and for each user loop on its books to retrieve books that matched the conditions.
When you say:
embeds_many :books
that actually produces an array of hashes inside MongoDB and then wraps some Mongoid stuff around that array and its elements. So you search embedded documents just like you'd search any other array of hashes.
For example, if your Book has a title field then you could say:
users = User.where('books.title' => /Pancakes/)
to find all the users with books about pancakes. Of course that gives you a bunch of Users rather than Books. Embedded documents don't exist on their own, they're just parts of their parent document, so you have to go through the parent. But, once you have some Users, you can extract the books you're interested in:
books = users.map(&:books).flatten.select { |b| b.title =~ /Pancakes/ }
You can also throw in an only if your Users are large and you don't want to pull whole Users out of MongoDB:
# Some versions of Mongoid will get upset if you don't include :id
books = users.only(:books, :id).map...
If you're doing this sort of thing a lot then maybe Book shouldn't be embedded inside User.

Sunspot search by id

Is there any way to search entity by id with subspot
like so:
Content.search do
with(:ids, [1,2,3])
end
Unfortunately the only way to achieve this is indexing the id field:
class YourModel < ActiveRecord::Base
searchable do
integer :id
# ...
end
end

Searching String Fields Using Sunspot and Rails

My team is attempting to implement Solr and Sunspot-Rails as a search provider for our application. Our story requires that certain string fields be searched in addition to the text fields. I have seen some people aggregate these fields into a consolidated indexing field (with a type of Text) with ActiveRecord callbacks. Is this my only hope or is there a wildcard argument that I am missing?
you can define your fields that will be indexed like this
class Post < ActiveRecord::Base
searchable do
text :title, :body
text :comments do
comments.map { |comment| comment.body }
end
string :sort_title do
title.downcase.gsub(/^(an?|the)/, '')
end
end
end
then you search them you can specify the fields you want to search like this
Post.search do
fulltext 'pizza' do
fields(:body, :title)
end
end
if you didn't specify fields it'll apply the search to all the text fields indexed
Post.search do
fulltext 'best pizza'
end

limiting fields returned from a mongoid polymorphic relation

I have a polymorphic relation in mongoid like the following one:
class Company
include Mongoid::Document
field :name, :type => String
has_many :posts, as: :postable
end
class Person
include Mongoid::Document
field :name, :type => String
has_many :posts, as: :postable
end
class Post
include Mongoid::Document
belongs_to :postable, polymorphic: true
end
I would like to sometimes (and not most of the time) load only some fields of the postable. In a non polymorphic relation (say only a Person has posts) I can do:
Person.only(:name).find(some_post.postable_id)
But is this possible in a polymorphic relation?
I can see a few ways of doing this but I am not sure which is the best. Complex relations are not a strength MongoDB and other NoSQLs and queries can get expensive if you start scanning multiple documents for your answers.
Using where:
Person.where(name: "name").posts.where(postable_id: "id")
Finding the parent from the post:
Post.where(id: "id").person.only(:name)
(note that postable_id and id are not the same value!)
However, be careful. If all you are doing is listing posts you are probably better off including the person's name in the post and writing a callback to update the person's name if they change their name. Alternatively, if you are linking to comments from a person why not include the comment IDs (or enough data to make the link) in the Person model so you can get all comments with one document call. Similarly if you are getting a count, use a callback to make a post count in the Person model so you aren't mapping hundreds of Posts every time.
I hope this helps, if not provide me with some more information and I'll update this.

Resources