MongoDB database design with embedded documents - mongodb

I have a few thousand strings (items) that I would like to translate. I have structured my MongoDB as follows:
#document = {:item => "hello", :translations => {:fr => {:name => "bonjour",
:note => "easy"}, :es => {:name => "hola", :note => "facil"}}}
The :translations field can contain many more languages and properties. I would like to run queries such as retrieving all items with no translations for a specific language, or retrieving all items having 'bonjour' as a French translation.
I don't see how I can do this. Is there a better way to structure my database for these purposes? I am using node.js.
Thanks.

I would like to run queries such as retrieving all items with no translations for a specific language,
.find({ 'translations.fr': {$exists:false} })
...or retrieving all items having 'bonjour' as a French translation.
.find({ 'translations.fr.name': "bonjour" })
Is there a better way to structure my database for these purposes?
I believe that you have the correct structure. You will have to become familiar with the Dot Notation.

I'd say that for your purpose the model is good. You need mongo dot notation, you can use $exists to look for fr and dot notation for bonjour -
find({ "fr.name" : "bonjour" })

Related

Mongoid, find object by searching by part of the Id?

I want to be able to search for my objects by searching for the last 4 characters of the id. How can I do that?
Book.where(_id: params[:q])
Where the param would be something like a3f4, and in this case the actual id for the object that I want to be found would be:
bc313c1f5053b66121a8a3f4
Notice the last for characters are what we searched for. How can I search for just "part" of my objects id? instead of having my user search manually by typing in the entire id?
I found in MongoDB's help docs, that I can provide a regex:
db.x.find({someId : {$regex : "123\\[456\\]"}}) // use "\\" to escape
Is there a way for me to search using the regular mongo ruby driver and not using Mongoid?
Usually, in Mongoid you can search with a regexp like you normally would with a string in your call to where() ie:
Book.where(:title => /^Alice/) # returns all books with titles starting with 'Alice'
However this doesn't work in your case, because the _id field is not stored as a string, but as an ObjectID. However, you could add (and index) a field on your models which could provide this functionality for you, which you can populate in an after_create callback.
<shameless_plug>
Alternatively, if you're just looking for a shorter solution to the default Mongoid IDs, I could suggest something like mongoid_token which makes it pretty easy to add shorter tokens/ids to your Mongoid documents.
</shameless_plug>

MongoDB - searching text

What is the best strategy for selecting mongodb entries in which a string value contains a set of words or phrases? I'm thinking of something equivalent to mysql's LIKE function, e.g.
WHERE (TEXT LIKE "% apple %") or (TEXT LIKE "% banana %")
I've seen options that involve tokenizing the string, but this would involve building unigrams for all the text, which would be huge no?
Mongo now supports text search since 2.4.
My experience has been pretty positive
http://docs.mongodb.org/manual/applications/text-search/
You start the server with setParameter text search enabled
Then enable the index on the collection
Then search with runCommand
MongoDB has no full text search capability right now, but it's easy to use external search engines like SOLR.
I strongly discourage you trying to rebuild text search with Regex or word stemming etc. yourself. You should rather focus on your app own features :)
I am using this combination: Mongoid, Sunspot and Mongoid-Sunspot. It works very well in production, and development setup is easy.
You can use the regular expression support in MongoDB queries. More details available # the following link
http://docs.mongodb.org/manual/reference/operator/regex/
Here are two examples should the above link move again in the future:
db.collection.find( { field: /acme.*corp/i } );
db.collection.find( { field: { $regex: 'acme.*corp', $options: 'i' } } );
Somehow MongoDB built-in text search failed to meet my requirements on an existing database which used a compound index. I am now using mongoose-search-plugin and it has been working superbly well. It uses natural stemming, and distance algorithms to return a relevance score.
User.search('Malaysia Car Food',{username:1},{}, function(err, u){
console.log('Search Results: '+JSON.stringify(u));
});

"LIKE" command in MongoDB(mongomapper)

how to use filter data as sql do "LIKE" in MongoDB, instead I using gem mongomapper on my rails apps? .thanks
If you're looking for partial matches on a string you can query with a regular expression. Here's the relevant part of the mongomapper docs:
http://api.mongodb.org/ruby/current/file.TUTORIAL.html#Querying_with_Regular_Expressions
Worth noting this from the Mongodb docs:
"For simple prefix queries (also called rooted regexps) like /^prefix/, the database will use an index when available and appropriate (much like most SQL databases that use indexes for a LIKE 'prefix%' expression). This only works if you don't have i (case-insensitivity) in the flags."
the closest thing to SQL LIKE would be /query/
ex:-
Person.where('name' => /John/).all => John F, John Doe, Johnny...etc
Edit: this is still case sensitive
try these it work for me :
#store_array=User.where(:$or => [{:first_name => /.#{#search_text}./i}, {:last_name => /.#{#search_text}./i}]).all();

restrict documents for mapreduce with mongoid

I implemented the pearson product correlation via map / reduce / finalize. The missing part is to restrict the documents (representing users) to be processed via a filter query. For a simple query like
mapreduce(mapper, reducer, :finalize => finalizer, :query => { :name => 'Bernd' })
I get this to work.
But my filter criteria is a little bit more complicated: I have one set of preferences which need to have at least one common element and another set of preferences which may not have a common element. In a later step I also want to restrict this to documents (users) within a certain geographical distance.
Currently I have this code working in my map function, but I would prefer to separate this into either query params as supported by mongoid or a javascript function. All my attempts to solve this failed since the code is either ignored or raises an error.
I did a couple of tests.
[results deleted, see below]
I'm using ruby 1.9.2, mongodb 1.6.5-x86_64, and the mongoid 2.0.0.beta.20, mongo 1.1.5 and bson 1.1.5 gems on MacOS.
What am I doing wrong?
Thanks in advance.
More Tests (problem partly solved):
User.where(:name.in => ["Arno", "Bernd", "Claudia"])
works, however when using mapreduce like this
mapreduce(..., :query => { :name.in => ['Arno', 'Bernd', 'Claudia'] })
results in the bson error serialize: keys must be strings or symbols (TypeError) mentioned above.
Replacing :name.in with 'name.in' or 'name.$in' makes the query return no results (guess this is passed as is to mongodb).
However
mapreduce(..., :query => { :name => { '$in' => ['Arno', 'Bernd', 'Claudia'] } })
works, but I didn't have any success with my geospatial query attempts, no matter how I wrote the expression.
mapreduce(..., :query => {:location => { "$near" => [ 13, 52, 1 ] } })
results in this error_message: Database command 'mapreduce' failed: {"assertion"=>"manual matcher config not allowed",....
If anyone could give me an idea how to write a geospatial query using near or within and working with mapreduce I would be very happy. (I didn't play with sets yet, see above).

MongoDB dbref in perl

Is there a way to do dbrefs using the Perl API? Its not here nor is it anywhere here.
Here s a sample schema:
book: name, publisher,isdn,{author}
author : name,date of birth
I could just add a field to serve as the reference but wanted to do it with dbref instead.
There are no helpers for it, yet. DBRefs are just normal hashes, though, so you can access/create them yourself. They have the form:
my $ref = {'$ref' => $collection_name, '$id' => $id};
See http://www.mongodb.org/display/DOCS/DB+Ref for more info.
It's also handled by MongoDBx::Class, but this is a fully fledged ORM so it may not fit your use case.
https://metacpan.org/pod/MongoDBx::Class
Its handle by MongoDBx::AutoDeref.
https://metacpan.org/pod/MongoDBx::AutoDeref