Searching in collection with self referencing objects - mongodb

I have a collection:
{
_id - ObjectId
name - string
location - string
..
parentId - ObjectId //link to parent object
}
I have a filter query and it works nice even with int values (in C#):
var q = Query.Matches(column, new BsonRegularExpression(string.Format("/^{0}/i", name)));
What should I do in order to search by the name of parent object? Of cause, using LINQ, there is no problem, but is it possible to conduct searching on the server side?

There are no joins in MongoDB, but you basically have two options:
Solution 1:
Query by the name and fetch the result (the parents)
For every document fetched, query again and fetch all documents where the _id and the parentId match (the children)
Solution 2:
Additionally to the parentId, also save the name of the parent's name with each document and query directly for parentName

There is not way to search by referenced object fields in mongodb. And in general monogdb is not relational database, so in my opinion it should not support any relations at all.
There is good known approach it is create additional field and store (denormalize) information on what you want search.
So, change your schema as follow to search on parent object name:
{
_id - ObjectId
name - string
location - string
..
parentId - ObjectId //link to parent object,
parentName
}
The main idea you should understand: mongodb is not realtional, no joins here, no relations.

Related

Mongo aggregate with objects in array to match to other document

I have 2 collections
Incident
{
_id:...,
suspects : [{id:...,...},{}...]
}
and
Suspect
{
_id:...
}
The suspects in the Incident document are nested object that is not the equal to the document in collection Suspects but a subset with an id that matches the suspect in the suspects collection.
I would like to query the db, either for the incidents and to attach at the array (or create new one) with the actual documents that matches the ids
or
Query for suspects with attached a property that is the incident document where the suspect id exists in the array.
If you have the id field in the Incident collection, and that is corresponding to the actual document id in the Suspect collection, you can use the lookup operator
https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
I've setup a sample code in this Mongo Playground. Let me know if you need further explanation :)

Put a prefix for ObjectID for MongoDB _id field

I'm trying to put a prefix before the auto generated _id, to identify from which collection came an id, but I still want to use the mongo unique id generator.
So I can know that this id model_5e1a51821c9d44000089e3e0 came from the Model collection.
Is there a solution for that without messing with random string ?
Edit
The _id need to be string castable, since I use it as id in a graphQL object. I need to differentiate ids because I use an union in my schema and resolver need to know in which table to find the data.
The _id can be generated within an application with the constructor ObjectId(). If you want to add a prefix for the generated field, you can use an embedded document as a field for the _id, like this:
_id: {
idPrefix: "Model",
_id: ObjectId("5e1bd112b7f18a490a4bafb5")
}
Other way of identifying if a document is from another collection is use a separate boolean field:
{
_id: ObjectId("5e1bd112b7f18a490a4bafb5"),
isFromModel: <boolean true or false>,
...
}
There are some options available to do this, I'm just trying to tell you the way how would I do if I need this.
Step 1: You can generate the document and it will return you ObjectId (_id) .
Step 2: Take that value and prefix it with model like this.
let _id=5e1a51821c9d44000089e3e0;let new_idValue="model_"+_id;
Step3: Now update your document by _id and push new value in place of if as
this.db.document.findByIdAndUpdate(_id,{$set:{{_id:new_idValue}})
This is what you can do. If you find some best solution than mine, let me know as well. I will highly appreciate.

Find the collection name from document._id in meteor (mongodb)

From the looks of the syntax for handling mongodb related things in meteor it seems that you always need to know the collection's name to update, insert, remove or anything to the document.
What I am wondering is if it's possible to get the collection's name from the _id field of a document in meteor.
Meaning if you have a document with the _id equal to TNTco3bHzoSFMXKJT. Now knowing the _id of the document you want to find which collection the document is located in. Is this possible through meteor's implementation of mongodb or vanilla mongodb?
As taken from the official docs:
idGeneration String
The method of generating the _id fields of new documents in this collection. Possible values:
'STRING': random strings
'MONGO': random Meteor.Collection.ObjectID values
The default id generation technique is 'STRING'.
Your best option would be to insert records within a pseudo transaction where the second step is to take the id and collection name to feed it into a reference collection. Then, you can do your lookups from that.
It would be pretty costly, though to construct your find's but might be a pattern worthwhile exploring if you are building an app where your users will be creating arbitrary data patterns.
You could accomplish this by doing a findOne on all of the collections:
var collectionById = function(id) {
return _.find(_.keys(this), function(name) {
if (this[name] instanceof Meteor.Collection) {
if (this[name].findOne(id)) {
return true;
}
}
});
};
I tested this on both the client and the server and it seemed to work when run in the global context.

Retrieve documents having array containing another document attribute

I am storing some kind of filesystem in Mongo, where directories are named categories.
The category JSON looks like:
{
"name":"CategoryChildLevel2",
"parentId":"2",
"otherAttribute":"anyVal",
"breadcrumb":[
{
"name":"RootCategory",
"id":"1"
},
{
"name":"CategoryChildLevel1",
"id":"2"
}
]
}
The FS categories are linked together with the parentId attribute.
I need to display the categories breadcrumbs.
Through user navigation, we can know where we are on the FS, but categories can be accessed directly by their ID (bookmarked category, search engine...), without any FS navigation.
To avoid recursive calls to the DB, to be able to get the breadcrumb, I have denormalized it.
The problem is that this breadcrumb is hard to keep up to date, because a top level category can be moved and thus all its childs breadcrumbs must be updated. There can be many child categories to update, and there are different ways to deal with this problem.
Some of them are secure but expensive (recursion), and others are faster but could lead to some inconsistencies.
Here what I'd like to know is if it is possible to do a query to retrieve categories that have a bad breadcrumb. I need a query that permits to do:
Retrieve all the categories that do not have: last array element
breadcrumb.id = parentId
I don't think the "last array element" part is possible, but it would also be nice to be able to do:
Retrieve all the categories that do not have:
breadcrumb.id contains parentId
Any solution, available in Scala or Java driver?
I'm using Salat/Casbah.
This question may help you to understand what I'm facing: Which DB would you use? MongoDB/Neo4j/SQL... all of them?
You can do the Retrieve all the categories that do not have: last array element breadcrumb.id = parentId query with a $where operator:
db.test.find({
// Find docs were breadcrumb is empty or its last element's id != parentId
$where: '!this.breadcrumb.length || this.breadcrumb[this.breadcrumb.length-1].id !== this.parentId'
})

Mongo DB best practice for a query WHERE IN with tags and childs

Well i'm planning a collection schema and i have dubt to how embed data inside tag field.
i have a colletion named products:
products
->_id
->product_name
->tags
i have then a tags collection:
tags
->_id
->tag_name
and i have a tags_child collection:
tags_childs
->_id
-> id_tag
->tag_child_name
now i need to save tags and tags_childs into products collection, so i tought it was good to save in products collection a field:
tags: [[_id_tag]:[_id_tag_child,_id_tag_child, ... etc],[_id_tag]:[_id_tag_child,_id_tag_child, ... etc]]
but i think is not the right way, cause i need to be able to query on products collection, filtering by tags and child_tags.
So for example i need to filter products by:
+product_name: 'roastbeef'
+ tag:'hot'
+ child tag : 'sauce'
or filter by:
+product_name: 'roastbeef'
+ tag: 'hot'
+ child tag:'sauce'
+ child tag:'knife'
+ tag:'dinner'
Parent tags are always required when filtering, while child tags are optional.
How do you implement a right collection to do this type of query at the end?
Reading over this; I described your schema a bit in detail here:
Schema Advice
There really isn't a reason to be holding this pivotal table, as in the end they are all just tags. You can still search for multiple tags within your database by going with the above suggested schema; along with showing all your available tags to and their relationship from the above schema; this way it cleans up your entire DB rather than muddying it with an extra table which MongoDB just doesn't need.
I'd highly recommend re-going through this e-book to just strengthen the understanding around the NoSQL format Mongo empowers you with.
Mongo Free eBook PDF