How to search on contents of a referenced field in morphia - mongodb

Lets say that I have classes like this:
public class Foo{
#id
ObjectID id;
#Reference
Bar bar;
long fooValue;
}
public class Bar {
#id
ObjectID id;
#Reference
Baz baz;
long barValue;
}
public class baz{
#id
ObjectID
String content;
}
If I want to load all foo objects in which the referenced baz has a certain value what syntax should I use? Lets see I want all foo in which the referenced baz.content value is "foobar" how can I do it? Would it be quicker to work backwards by looking up all baz and then finding all bar that reference it etc?

This won't work (well) with MongoDB. What you are trying to do is a JOIN, which doesn't exist.
What you can do is:
Query Baz, which gets you a Baz.ObjectId (for each match).
Query the Bar that references the Baz.ObjectId, which gets you a Bar.ObjectId
Do the same for Foo referencing the Bar.ObjectId
So for each matched document in Baz you'll need two more queries to get its Foo.
Could you embed Baz into Bar and Bar into Foo? Then you'd only need a single query.

Related

Store Object in database which have array of objects

How can we store object in database which have array of object inside it.
For ex.
Class Foo {
public List<object> Bar = new List<object>();
}
Can give answer in php or c#.
One thing you could do is have table Foo, table Bar, and table FooBar. Foo and FooBar would have some sort of unique identifier with them, and FooBar would have the map. The query you could execute is
SELECT Foo.Id AS FooId, Bar.Id AS BarId, Bar.Column1, Bar.Column2
FROM Foo
INNER JOIN FooBar
ON Foo.Id = FooBar.FooId
INNER JOIN Bar
ON FooBar.BarId = Bar.Id
Note that I'm no DBA or SQL expert, so there may be a better way of doing this.

Composite Primary key in JPA

The EmbeddedId or IdClass annotation is used to denote a composite primary key.
How can i use composite primary key without ( EmbeddedId or IdClass ) ?
If it is possible to use composite primary key without ( EmbeddedId or IdClass ) then how can i use EntityManager.find( Entity Class , Object primaryKey) method to find entity in case of composite primary key(Multiple Primarykey) (because of no IdClass or EmbeddedId) .
EclipseLink take List of pk in the find() operation but if composite pk key defined in example -
Entity Person {
#Id
String username;
#Id
String emailId;
#Basic
String firstName;
#Basic
String lastName;
}
List list = new ArrayList();
list.add(${username}); //Run time value
list.add(${emailId}); //Run time value
then EnitityManager.find(list) will take these arguments , is i am right?
If i am assuming correct then how will EnitityManager.find() operation will know that List 1st argument is username or emailId pk value (means sequence of composite pk fields value)
Let me give my thoughts about it.
find
<T> T find(java.lang.Class<T> entityClass,
java.lang.Object primaryKey)
In order to find an entity of class Person, you should use something like
find(Person.class, Object primaryKey)
As you have a composed key, you should have a IdClass or EmbeddedId like this.
public class PersonKey implements Serializable{
String username;
String emailId;
public PersonKey(String username, String emailId){
//Add lines for correct constructor
}
//Override hascode and equals
}
Then you can find objects based on that key.
find(Person.class, personKey);
your key need to be something like this.
PersonKey personKey = new PersonKey(1,1);
Person p = find(Person.class, personKey);
FIND DON'T ACCEPT LISTS IN PURE JPA !!, accept and return only ONE managed object. If you would use find to retrieve several objects you should call the method N times passed the keys you want to find.
If you use find passing a list you will see something like this.
org.springframework.dao.InvalidDataAccessApiUsageException:
Provided id of the wrong type for class domain.model.Person. Expected:
class domain.key.PersonKey, got class java.util.ArrayList; nested
exception is java.lang.IllegalArgumentException: Provided id of the
wrong type for class
com.staples.sa.pricemart.domain.model.ItemFileEntity. Expected: class
com.staples.sa.pricemart.domain.key.ItemFileKey, got class
java.util.ArrayList
It seems eclipseLink have find that you can do that, but in order to make you application more portable try to use find as is described in JPA.
You should give an entity as the primary key:
Person id = new Person();
id.setUsername("Username");
id.setEmailId("EmailId");
entityManager.find(Person.class, id);
JPA will use the the fields annotated with #Id to find the the record You need.
You should be able to use a List with the find() operation in EclipseLink.

How store objects in MongoDb without assembly fully qualified name

I store item that contains fields like Dictionary
In mongo this field has _t = System.Collections.Generic.Dictionary`2[System.String,[Namespace.MyType, Namespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=89b48272fdae8cae]]
I don't need Version and PublicKeyToken and farther this be a trouble with next version of assembly
How can I store data with _t property like System.Collections.Generic.Dictionary`2[System.String,[Namespace.MyType]]?
The type discriminator is used for inheritance and resolving declared type to stored type.
If you have a concrete class with a concrete property, you should not need a discriminator.
Let's say you have a property on a class:
public class Foo : MyBase{
...
public string Title {get;set;}
}
public class Bar: MyBase{
...
public string Title {get;set;}
}
The driver might be able to map that IN to a string array and store in mongodb
{_id: ..., Title: "Hello" }
On the way OUT though, the driver has to decide what the BSON array would become. Absent a type discriminator, should it generate an instance of : Foo? Bar? MyBase?
If you have a class that has-a concrete dictionary rather than is-a dictionary, you can avoid much of this.

MongoDB: query by #DBRef

I have a class hierarchy designed for store user notifications:
#Document
public class Notification<T> {
#Id
private String id;
#DBRef
private T tag;
...
}
#Document
public class NotificationA extends Notification<WrappedA> {
}
#Document
public class NotificationB extends Notification<WrappedB> {
}
...
This is useful for returning polymorphic arrays, allowing me to store any kind of data in the "tag" field. The problem starts when the wrapped objects contains #DBRef fields:
#Document
public class WrappedA {
#Id
private String id;
#DBRef
private JetAnotherClass referenced;
...
}
Queries on the fields of "tag" works fine:
db.NotificationA.find( {"tag.$id": ObjectId("507b9902...32a")} )
But I need to query on the fields of JetAnotherClass (two levels of #DBRef fields). I've tried with dot notation and also with subobjects but it returns null:
Dot notation:
db.NotificationA.findOne( {"tag.$referenced.$id": ObjectId("508a7701...29f")} )
Subobjects:
db.NotificationA.findOne( {"tag.$referenced": { "_id": ObjectId("508a7701...29f") }} )
Any help?
Thanks in advance!
Since you look like you are only querying by _id I believe you can do:
db.NotificationA.findOne({"tag.$id": ObjectId("blah")});
However:
But I need to query on the fields of JetAnotherClass (two levels of #DBRef fields).
DBRefs are not JOINs, they are merely a self describing _id in the event that you do not know the linking collection it will create a helper object so you don't have to code this yourself on the client side.
You can find more on DBRefs here: http://docs.mongodb.org/manual/applications/database-references/
Basically you can query the sub fields within the DBRef from the same document, i.e.: DBRef.$_id but you cannot, server-side, resolve that DBRef and query on the resulting fields.

Lucene 'join' how-to?

Using Nhibernate.Search at the moment.
Some code for context:
[Indexed]
class foo {
[DocumentId]
int id {get;set;}
bar bar {get;set;}
}
[Indexed]
class bar {
[DocumentId]
int id {get;set;}
}
Question:
How to retrieve all foos where foo.bar.id==1 using IFullTextQuery?
If you want to include related information into the foo index you may look into the IndexedEmbeddedAttribute. This will allow you to query for relationships such as if there was a Name property on the bar object you could create a query such as this
IFullTextQuery query = search.CreateFullTextQuery("bar.Name:Arnis");
query.List<foo>();
Seems that [IndexedAttribute] is an answer.