How to find objectId as an foreign key in mongo - mongodb

How can I find the value of ObjectId in whole database for any field in mongo ,
it might be use in some collections for various fields as a reference?
"fourk_runs": [{
"Objectid": "6299b9f00f09ff045cc15d"
}],
"fourk_pass_fail": [{
"Objectid": "6299b9f00f09ff045cc152"
}],
"dr_runs": [{
"Objectid": "6299b9f00f09ff045cc154"
}],
I try this command , but it does not work
db.test.find( { $text: { $search: "4c8a331bda76c559ef04" } } )

In MongoDB, the references are mostly used for the normalization process. The references from the children's table (usually an ObjectID) are then embedded in the parent table. When reading the information, the user has to perform several queries in order to retrieve data from multiple collections.
For example, we will take the next two collections, parts and products. A product will contain many parts that will be referenced in the product collection.
parts Collection:
db.parts.findOne()
{
_id : ObjectID('1111'),
partno : '7624-faef-2615',
name : 'bearing',
price: 20,000
}
products Collection:
db.products.findOne()
{
name : 'wheel',
manufacturer : 'BMW',
catalog_number: 1134,
parts : [ // array of references to Part documents
ObjectID('1111'), // reference to the bearing above
ObjectID('3f3g'), // reference to a different Part
ObjectID('234r'),
// etc
]
}
To receive the parts for a particular product, we will first have to fetch the product document identified by the catalog number:
db.products.findOne({catalog_number: 1134});
Then, fetch all the parts that are linked to this product:
db.parts.find({_id: { $in : product.parts } } ).toArray();

Related

MongoDB Schema optimization for contacts

I am storing my contacts in mongodb like this but main drawback of this schema is I am not able to store 40k-50k contacts in one document due to limit of 16mb.
I want to change my schema now. So can anyone please suggest me best way to redesign this.
Here is my sample doucument
{
"_id" : ObjectId("5c53653451154c6da4623a77"),
"contacts" : [{
name:"",
email:"",
group:[5c53653451154c6da4623a79]
}],
"groups" : [{
_id: ObjectId("5c53653451154c6da4623a79"),
group_name:"test"
}],
}
According to you document sample, contacts belongs to a group.
In that scenario, there are different ways to end up with a better schema:
1- Document embedding:
You will have an array of contacts inside each group document.
collection groups:
{
"_id": ObjectId("5c53653451154c6da4623a79"),
"group_name":"test",
"contacts": [
{
"name":"something",
"email":"something",
},
{
"name":"something else",
"email":"something else",
}
]
}
2- Document referencing:
You will have two collections - contacts and groups - and store a group reference inside each contact.
collection contacts:
{
"_id" : ObjectId("5c53653451154c6da4623a77"),
"name":"something",
"email":"something",
"groups":["5c53653451154c6da4623a79"]
},
{
"_id" : ObjectId("5c536s7df9sd7f987d9s7d98"),
"name":"something else",
"email":"something else",
"groups":["5c53653451154c6da4623a79"]
}
collection groups:
{
"_id": ObjectId("5c53653451154c6da4623a79"),
"group_name":"test"
}
Why are we referencing group inside contact and not the contrary? Because we probably will have more contacts than groups. This way we have smaller documents with smaller "reference arrays".
The path you will follow depends a lot on how many contacts you have per group. If this number is small, I would take the Document Embedding approach, for the sake of simplicity and access easiness. If you have a large number of contacts per group, I would use Document Reference, to have smaller documents.

Use MongoDB object ID as a unique key within a document

I'm using MongoDB for my senior project to allow donors to sponsor children for an organization similar to world vision and I'm wondering about the feasibility of reusing the ObjectID datatype as a unique id within a json array.
example donor document:
{
_id: ObjectID(x), // this document's _id
name: "Josh",
last_name: "Richard",
address: "2 Happy Lane",
city: "New York",
state: "New York",
credit_card: 999999999999999,
cvv: 999,
exp: 3/18,
transactions: [
{
_id: ObjectID(x), // this is what i'm asking about
child_ids: [
ObjectID(x), // this is the _id of a doc in another collection
ObjectID(x) // this is also the _id of a doc in another collection
]
},
{
_id: ObjectID(x),
child_ids: [
ObjectID(x), // this is the _id of a doc in another collection
]
}
]
}
The transactions._id is what I'm looking for feedback on. I need this to be unique so that I can differentiate orders from each other, but I'd rather not create a new collection for storing these as documents and instead keep it all in the donor doc. Any thoughts?
EDIT: What I'm not curious about is the technical uniqueness of an ObjectID. What I'm looking to find out is if it's realistic to "repurpose" the ObjectID as a unique key to then use later in application logic. I need some way to uniquely identify objects in an array across all instances of that type of array in every document. I.E.: Every transaction needs to have it's own unique identifier and those transactions are stored in arrays in many different documents within the same collection.

Query MongoDB for multiple ObjectIDs in Array

I have a collection "users" in my Database. A user can be a member of several teams.
I am using an Array to reference the team IDs.
{ _id: ObjectId("552544fd600135861d9e47d5)",
name : "User1",
teams: [
"5527a9493ebbe2452666c238",
"5527b1be3371e3a827fa602c"
]
}
The teams are nothing more than a collection of:
{ _id: ObjectId("5527a9493ebbe2452666c238"),
name: "Team 1"
}
{ _id: ObjectId("5527b1be3371e3a827fa602c"),
name: "Team 2"
}
Now I want to get the names of all the teams in which the user is a member.
I have only found the way of querying it this way:
db.teams.find(
{_id:{$in:
[ObjectId("5527a9493ebbe2452666c238"),
ObjectId("5527b1be3371e3a827fa602c")]
}})
To do this, I would need to create an array specifically for this query. I would rather try to avoid this, because I already have the IDs available as an array in the string format. Something like this would be great:
db.teams.find(
{_id:{$in:
["5527a9493ebbe2452666c238",
"5527b1be3371e3a827fa602c"] // Strings here, not ObjectIDs
}})
But this does not work. Is there any comfortable way of querying an ObjectID with a set of string IDs?
Thanks & regards
Rolf
You could use a combination of mongodb's findOne() and find() cursor methods together with the native JavaScript map method to first get the team id's for a specific user (which will be a string array), then use the map function to map the teams' string id's array to an ObjectId's array, and finally query the teams collection with the resulting array as the $in operator expression:
var teams = db.users.findOne({"name": "User1"}).teams;
var obj_ids = teams.map(function (item){ return ObjectId(item)});
db.teams.find({ "_id": { "$in": obj_ids } });
Output:
/* 0 */
{
"_id" : ObjectId("5527a9493ebbe2452666c238"),
"name" : "Team 1"
}
/* 1 */
{
"_id" : ObjectId("5527b1be3371e3a827fa602c"),
"name" : "Team 2"
}

Inline/combine other collection into one collection

I want to combine two mongodb collections.
Basically I have a collection containing documents that reference one document from another collection. Now I want to have this as a inline / nested field instead of a separate document.
So just to provide an example:
Collection A:
[{
"_id":"90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"someValue": "foo"
},
{
"_id":"5F0BB248-E628-4B8F-A2F6-FECD79B78354",
"someValue": "bar"
}]
Collection B:
[{
"_id":"169099A4-5EB9-4D55-8118-53D30B8A2E1A",
"collectionAID":"90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"some":"foo",
"andOther":"stuff"
},
{
"_id":"83B14A8B-86A8-49FF-8394-0A7F9E709C13",
"collectionAID":"90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"some":"bar",
"andOther":"random"
}]
This should result in Collection A looking like this:
[{
"_id":"90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"someValue": "foo",
"collectionB":[{
"some":"foo",
"andOther":"stuff"
},{
"some":"bar",
"andOther":"random"
}]
},
{
"_id":"5F0BB248-E628-4B8F-A2F6-FECD79B78354",
"someValue": "bar"
}]
I'd suggest something simple like this from the console:
db.collB.find().forEach(function(doc) {
var aid = doc.collectionAID;
if (typeof aid === 'undefined') { return; } // nothing
delete doc["_id"]; // remove property
delete doc["collectionAID"]; // remove property
db.collA.update({_id: aid}, /* match the ID from B */
{ $push : { collectionB : doc }});
});
It loops through each document in collectionB and if there is a field collectionAID defined, it removes the unnecessary properties (_id and collectionAID). Finally, it updates a matching document in collectionA by using the $push operator to add the document from B to the field collectionB. If the field doesn't exist, it is automatically created as an array with the newly inserted document. If it does exist as an array, it will be appended. (If it exists, but isn't an array, it will fail). Because the update call isn't using upsert, if the _id in the collectionB document doesn't exist, nothing will happen.
You can extend it to delete other fields as necessary or possibly add more robust error handling if for example a document from B doesn't match anything in A.
Running the code above on your data produces this:
{ "_id" : "5F0BB248-E628-4B8F-A2F6-FECD79B78354", "someValue" : "bar" }
{ "_id" : "90A26C2A-4976-4EDD-850D-2ED8BEA46F9E",
"collectionB" : [
{
"some" : "foo",
"andOther" : "stuff"
},
{
"some" : "bar",
"andOther" : "random"
}
],
"someValue" : "foo"
}
Sadly mapreduce can't produce full documents.
https://jira.mongodb.org/browse/SERVER-2517
No idea why despite all the attention, whining and upvotes they haven't changed it. So you'll have to do this manually in the language of your choice.
Hopefully you've indexed 'collectionAID' which should improve the speed of your queries. Just write something that goes through your A collection one document at a time, loading the _id and then adding the array from Collection B.
There is a much faster way than https://stackoverflow.com/a/22676205/1578508
You can do it the other way round and run through the collection you want to insert your documents in. (Far less executions!)
db.collA.find().forEach(function (x) {
var collBs = db.collB.find({"collectionAID":x._id},{"_id":0,"collectionA":0});
x.collectionB = collBs.toArray();
db.collA.save(x);
})

Adding indexes in mogodb

I currently have a mongodb database which is pretty unstructured. I am attempting to extract all the followers of a given set of profiles on twitter. My database looks like this:
{'123':1
'123':2
'123':3
'567':8
'567':9
}
Where each key is a user and the value is a single follower. When I attempt to create an index on these keys, I simply run out of the available index as I have a lot of users (8 million). After googling, I find that the maximum number of indexes I can have is about 64. How do I create a proper indexing on this database? OR would you suggest a different way for me to store my data?
You should structure your data differently.
I would recommend you to have a collection of "user" documents, where every user has an array "followers". This array should be filled with unique identifiers of the users who follow (like name, _id or your own ID number).
{ name: "userA",
followers: [
"userB",
"userC"
]
},
{ name: "userB",
followers: [
"userD",
"userF"
]
},
You can then create an index on the followers field to quickly find all users who follow an other user. When you want to find all users who follow the users "userX", "userY" and "userZ", you would then do it with this query:
db.users.find({followers: { $all: ["userX", "userY", "userZ" ] } });
Edit:
To add a follower to a user, use the $push operator:
db.users.update({name:"userA"}, { $push: { followers: "userB" } } );
The $pull operator can be used to remove array enries:
db.users.update({name:"userA"}, { $pull: { followers: "userB" } } );