MongoDB and NoRM - Querying collection against a list of parameters - mongodb

I need to query a collection based on a list of parameters.
For example my model is:
public class Product
{
string id{get;set;}
string title{get;set;}
List<string> tags{get;set;}
DateTime createDate{get;set;}
DbReference<User> owner{get;set;}
}
public class User
{
string id{get;set;}
...other properties...
}
I need to query for all products owned by specified users and sorted by creationDate.
For example:
GetProducts(List<string> ownerIDs)
{
//query
}
I need to do it in one query if possible not inside foreach. I can change my model if needed

It sounds like you are looking for the $in identifier. You could query products like so:
db.product.find({owner.$id: {$in: [ownerId1, ownerId2, ownerId3] }}).sort({createDate:1});
Just replace that javascript array [ownerId1, ...] with your own array of owners.
As a note: I would guess this query is not very efficient. I haven't had much luck with DBRefs in MongoDB, which essentially adds relations to a non-relational database. I would suggest simply storing the ownerID directly in the product object and querying based on that.

The solution using LINQ is making an array of user IDs and then do .Contains on them like that:
List<string> users = new List<string>();
foreach (User item in ProductUsers)
users .Add(item.id);
return MongoSession.Select<Product>(p => users .Contains(p.owner.id))
.OrderByDescending(p => p.createDate)
.ToList();

Related

Firestore query on collection

I have list of Collection IDs. Is there any way I can query and get all the documents under these collection ids? without iterating to each id in the list.
Thank you for your time
According to your last comment, I understand that you want to get all documents within a single collection and not to query multiple collections, which is not possbile for the moment in Firestore.
If you have a list of ids, then simply iterate over it and create for each id in the list the corresponding DocumentReference and then add all those references to a List<DocumentReference>. After that, iterate over the new list and for each reference create a Task and then add all those Tasks objects to List<Task<DocumentSnapshot>>.
In the end, just pass the list of Tasks to Tasks's whenAllSuccess() method:
Tasks.whenAllSuccess(tasks).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
#Override
public void onSuccess(List<Object> list) {
//Do what you need to do with your list
for (Object object : list) {
YourObject yb = ((DocumentSnapshot) object).toObject(YourObject.class);
Log.d("TAG", yb.getPropertyName);
}
}
});
In code it looks like my answer from this post:
Android Firestore convert array of document references to List<Pojo>

multiple nested navigation properties EF ?

i have in my database a User has list of Subscriptions, each subscription has a Category, each category has list of Paths, each path has list of Articles ?
Model
class User {
ICollection<Subscription> Subscriptions;
}
class Subscription {
Category category;
}
class Category {
ICollection<Path> paths;
}
class Path{
ICollection<Article> Articles;
}
my question
How to retrieve all Articles for a specific user ?
Using a combination of Select and SelectMany statements, you are able to traverse your entities and find the collection you need:
var allUserArticles = myUser.Subscriptions
.Select(sub => sub.Category) //take the category from each subscription
.SelectMany(cat => cat.Paths) //Take each path from each category, put them in a single list
.SelectMany(path => path.Articles) //Take each article from each path, put them in a single list
.ToList();
Note that if these entities need to be loaded from your database, that EF either needs to implement eager loading, or you have to make sure that all needed related entities are retrieved before running the above statement. Unexpected nulls can cause your output to be incorrect.
However, I have no info on this as it is missing from the question, so I can't know your specific case.

How to get result by joining two collections (tables) [Cakephp/MongoDB]

I am using https://github.com/ichikaway/cakephp-mongodb.git plugin for accessing mongodb datasource.
I have two Models: Teachers and Subject. I want joint find result on Teacher and Subject.
Here are my two models:
Teacher:
<?php
class Teacher extends AppModel {
public $actsAs = array('Containable');
public $hasOne = array('Subject');
public $primaryKey = '_id';
var $mongoSchema = array(
'name'=>array('type'=>'string'),
'age'=>array('type'=>'string'),
'subjectid'=>array('type'=>'string'),
'created'=>array('type'=>'datetime'),
'modified'=>array('type'=>'datetime'),
);
Subject:
<?php
class Subject extends Model {
public $actsAs = array('Containable');
public $belongsTo= array('Teacher');
public $primaryKey = '_id';
var $mongoSchema = array(
'name'=>array('type'=>'String'),
'code'=>array('type'=>'String'),
'created'=>array('type'=>'datetime'),
'modified'=>array('type'=>'datetime')
);
In Teachers Controller to get joint result, I did:
$results = $this->Teacher->find('all',array('contain'=>array('Subject')));
$this->set('results', $results);
But I am not getting any result from Subjects Collections.
Here is what I am getting:
array(5) {
[0]=>
array(1) {
["Teacher"]=>
array(7) {
["_id"]=>
string(24) "52e63d98aca7b9ca2f09d869"
["name"]=>
string(13) "Jon Doe"
["age"]=>
string(2) "51"
["subjectid"]=>
string(24) "52e63c0faca7b9272c09d869"
["modified"]=>
object(MongoDate)#78 (2) {
["sec"]=>
int(1390820760)
["usec"]=>
int(392000)
}
["created"]=>
object(MongoDate)#79 (2) {
["sec"]=>
int(1390820760)
["usec"]=>
int(392000)
}
}
}
I am a cakephp/mongoDB rookie only, Please guide me to get the desired result.
Edit: I read that mongoDb don't support Join Operation. Then How to manually do it? I mean I can write two find query on each Model, then how to combine both array and set it to view?
As you said, MongoDB does not support joins. Documents in query results come directly from the collection being queried.
In this case, I imagine you would query for Teacher documents and then iterate over all documents and query for the Subject documents by the subjectid field, storing the resulting subject document in a new property on the Teacher. I'm not familiar with this CakePHP module, but you may or may not need to wrap the subjectid string value in a MongoId object before querying. This depends on whether or not your document _id fields in MongoDB are ObjectIds or plain strings.
If Subjects only belong to a single teacher and you find that you never query for Subjects outside of the context of a Teacher, you may want to consider embedding the Subject instead of simply storing its identifier. That would remove the need to query for Subjects after the fact.

query based on matching elements in DBRef list for mongodb using spring-data-mongodb

I am pretty new to mongodb. I am using spring-data-mongodb for my queries from java. Please guide me if this is achievable.
Say I have two objects "Car" and "User" as following, where car has list of users,
Class Car {
#Id
String id;
String model;
#DBRef
List<User> users;
#DBRef
Company company;
}
Class User {
#Id
String id;
String name;
}
I want to find all cars for a user, (find all cars where car.users has given user)
Is it possible to achieve using spring-data-mongodb?
It's pretty easy if there was only one DBRef element, eg, for company I can write a query like this,
new Query(Criteria.where("company.$id").is(new ObjectId(companyId)))
But, how to achieve this if there is a list of elements referenced as DBRef??
Thanks for help.
Querying for one element on an array is exactly like query for a field equality. You could read the MongoDB documentation here. So your query will be:
new Query(Criteria.where("users.$id").is(new ObjectId(userId)))
in repository interface type this query on the method:
#Query("{'company' :{'$ref' : 'company' , '$id' : ?0}}")
Company find(String companyId);

Having a list of strings represented in a database using ORMLite

First of I am new to ORMLite. I would like my model class to have a field which is a list of strings, that would eventually hold a list of tags for my model object.
Which ORMLite annotations should I use?
Firstly I don't want to have a table of all tags, and then use the #ForeignCollectionField.
Also I thought of using the #DatabaseField(dataType=DataType.SERIALIZABLE) annotation, but it turns out that List<String> doesn't implement the Serializable interface.
What are your suggestions?
First of all, List doesn't implement Serializable but ArrayList certainly does as well as most of the common collection implementations. But storing a huge list is probably not the best of doing this from a pure object model standpoint.
So why don't you want to have a table of all tags? That's the best way from a pure model standpoint. It will require a 2nd query if you need them every time. That's the way hibernate would store a list or array of tags.
After reading your comment #creen, I still think you do want a table of tags. Your model class would then have:
#ForeignCollectionField
Collection<Tag> tags;
The tags table would not have a single tag named "red" with multiple model classes referring to it but multiple "red" entries. It would look like:
model_id name
1 "red"
1 "blue"
2 "red"
3 "blue"
3 "black"
Whenever you are removing the model object, you would first do a tags.clear(); which would remove all of the tags associated with that model from the tags table. You would not have to do any extra cleanup or anything.
No need to go for #ForeignCollectionField for simple String Array
Change your code
#DatabaseField(dataType=DataType.SERIALIZABLE)
List<String> users;
to
#DatabaseField(dataType = DataType.SERIALIZABLE)
String[] users;
Database doesn't want to store dynamically grow able arrays. That is the reason it allows only static array like string[] and not List.
I added two properties... one that gets written to the database as a csv string and the other that translates this:
[Ignore]
public List<string> Roles
{
get
{
return new List<string>(RolesCsv.Split(new char[] { ',' }));
}
set
{
RolesCsv = string.Join(",", value);
}
}
public string RolesCsv { get; set; }