Append fields from a document to other document having matching field MongoDB - mongodb

I am trying to write MongoDB query to accomplish something which is explained below. I don't know whether it is possible in mongoDB or not. I know how to insert a field in single document or multiple document but my problem is little advance to that.
I have a collection (say for "procs") having 5000 documents like:
{
"sid": 1
"procs": [
{
"post_time": 0,
"p_start": 1487303363.8170002,
"pid": 1
}
]
}
Here is the another document-2 from different collection(say for "acqs"):
{
"sn": 10302301,
"date": "2017-12-11",
"sid": 1
"acqs": [{
"aqid": 2,
"aq_end": 1487305607.342
}
]
}
This collection also contains around 5000 documents.
Now i want to insert "sn" and "date" fields from document 2 to document 1 corresponding to same "sid" field values.
so i want output something like this:
{
"sn": 10302301,
"date": "2017-12-11",
"sid": 1
"procs": [{
"post_time": 0,
"p_start": 1487303363.8170002,
"pid": 1
}
]
}

In mongoDb , you can use $lookup
db.procs.aggregrate([
{
$lookup:
{
from: "acqs",
localField: "sid",
foreignField: "sid",
as: "procs_docs"
}
}
])
Result Will be like :
{
"sn": 10302301, "date": "2017-12-11", "sid": 1 ,
"acqs": [{ "aqid": 2, "aq_end": 1487305607.342 } ]
"procs_doc": ["sid": 1,procs:{ "post_time": 0, "p_start": 1487303363.8170002, "pid": 1 } ] }
If you are using mongoose then you can use populate method of mongoose ,which lets you reference documents in other collections.

Related

Update an array item of Mongodb with $and query

Hi I am trying to increment the count of the matching requirement in an array. My sample collection looks like the following:
{
"_id": ObjectId("60760ba2e870fa518f2ae48b"),
"userId": "6075f7289822d94dca8066b4",
"requirements": [
{
"searchText": "zee5",
"planType": "basic",
"mode": "PRIVATE",
"count": 32.0
},
{
"searchText": "sony",
"planType": "standard",
"mode": "PUBLIC",
"count": 12.0
},
{
"searchText": "prime",
"planType": "premium",
"mode": "PRIVATE",
"count": 2
}
]
}
If a user searches for prime, with filter premium and PRIVATE, then the count of the last requirement should be updated. If he searches for prime, with filter standard and PRIVATE, then the new requirement will be inserted with count 1.
I am doing in two steps. First I fire an update with the following query and then if no update, I fire a push query with count 1:
db.getCollection('userProfile').update({ "$and" : [{ "requirements.searchText" : {$eq:"prime"}}, {"requirements.mode" : {$eq: "PUBLIC"}}, {"requirements.planType": {$eq: "standard"}}, { "userId" : "6075f7289822d94dca8066b4"}]}, {$inc: {"requirements.$.count" : 1}})
I was expecting that the above query will not update any requirement, since there is no exact match. Interestingly, it increments the count of the second requirement with (sony, standard, public). What is wrong with the query? How can I get it right?
Demo - with Update - https://mongoplayground.net/p/-ISXaAayxxv
Demo No update - https://mongoplayground.net/p/88bTj3lz7U_
Use $elemMatch to make sure all properties are present in the same object inside the array
The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria.
db.collection.update(
{
"requirements": {
$elemMatch: { "searchText": "prime","mode": "PUBLIC", "planType": "standard" }
},
"userId": "6075f7289822d94dca8066b4"
},
{ $inc: { "requirements.$.count": 1 } }
)
Problem -
Your current query will match any document with all these fields in
requirements array in any object, if they match 1 property in 1 index of the array and another match in the next index query will find the document valid.
"searchText": "prime",
"mode": "PUBLIC",
"planType": "standard"

Ensuring exactly N items with value X remain in an array with mongodb

Assuming we have a document in my MongoDB collection like the following:
{
"_id": "coffee",
"orders": [ "espresso", "cappuccino", "espresso", ... ],
}
How do I use a single update statement that ensures there are exactly say 2 espressos in this document, without knowing how many there are to begin with?
I know that using 2 consecutive statements I can do
db.test.update(
{ _id: "coffee" },
{ "$pull": { "orders": "espresso" } }
);
followed by
db.test.update(
{ "_id": "coffee" },
{ "$push": { "orders": { "$each": ["espresso", "espresso"] } } }
);
But when combining both into a single statement, MongoDB balks with an error 40, claiming Updating the path 'orders' would create a conflict at 'orders' (understandable enough - how does MongoDB what to do first?).
So, how can I do the above in a single statement? Please note that since I'll be using the above in the context of a larger unordered bulk operation, combining the above in an ordered bulk operation won't work.
Thanks for your help!

Put properties with different name in one field in MongoDB

I am getting requests from different devices as Json. Some of them show temperature as "T", some other as "temp" and it can be different in other devices. is that possible to define in MongoDB to put all of these values in single field "temperature"?
Doesn't matter if it is "temp" or "T" or "tempC", just put all of them in "temperature" field.
Here is an example of my data:
[
{ "ip": "12:3B:6A:1A:E6:8B", "type": 0, "t": 37},
{ "ip": "22:33:66:1A:E6:8B", "type": 1, "temperature": 40},
{ "ip": "1A:3C:6A:1A:E6:8B", "type": 1, "temp": 30}
]
I want to put temp, t and temperature in Temperature field in my collection.
You can use $ifNull operator to control which value should be transferred into your output, like below:
db.col.aggregate([
{
$addFields: { Temperature: { $ifNull: [ { $ifNull: [ "$t", "$temperature"] }, "$temp" ] } }
},
{
$project: {
t: 0,
temperature: 0,
temp: 0
}
}
])
This will merge that three fields into one Temperature taking first not empty value. Additionally if you want to update your collection, you can add $out as a last aggregation stage like { $out: col } but keep in mind that it will entirely replace your source collection.
I think mongodb supports regular expression but they are meant to search datas, not to insert them based on fieldname matches.
I am quite sure you shall use some kind of facade in front of your database to achieve that.

mongodb: return an array of document ids

Is it possible to query mongodb to return array of matching document id values, without the related keys?
Please consider following 'parent' data structur:
{
"_id": ObjectId("52448e4697fb2b775cb5c3a7"),
"name": "Peter",
"children": [
{
"name": "joe"
}
]
},
{
"_id": ObjectId("52448e4697fb2b775cb5c3b6"),
"name": "Marry",
"children": [
{
"name": "joe"
}
]
}
I would to query for an array of parent _ids whose children have the name "joe"
For provided sample data, I would like the following output returned from mongo:
[ObjectId("52448e4697fb2b775cb5c3a7"), ObjectId("52448e4697fb2b775cb5c3b6")]
I know that I can query for an output like this, which also contains the keys
[{"_id": ObjectId("52448e4697fb2b775cb5c3a7")}, {"_id": ObjectId("52448e4697fb2b775cb5c3b6")}]
However I need to push above array to another document with an update operation like this:
db.statistic.update({"date": today}, {$push: {"children": [ObjectId("52448e4697fb2b775cb5c3a7"), ObjectId("52448e4697fb2b775cb5c3b6")]}}, true, false)
I would like to avoid sorting out the document structure, in case it is possible to just return an array containing the appropriate values using mongo
It should be possible by
db.coll.distinct("_id", {"children.name": "joe"})

Duplicating a Mongoose document with subdocs, duplicated id of subdocs are allowed?

To clarify: I have a document with a subdoc. I create a new document with the same data of the other one and it gets a new id. However, when I copy the subdoc array they do not get a new id.
Are subdocs id local to the parent doc? I.e. would the following be a problem?
[
{
"__v": 1,
"_id": "5214af03a9f53efa61000004",
"name": "Foo",
"subdocs": [
{
"thing": "value",
"_id": "5214af03a9f53efa61000006"
}
]
},
{
"__v": 0,
"name": "Foo",
"_id": "5214af03a9f53efa61000014",
"subdocs": [
{
"thing": "value",
"_id": "5214af03a9f53efa61000006"
}
]
}
]
There is a unique index on the _id field of documents stored directly in a collection, but not for embedded documents, nor is there any requirement that embedded documents have an _id field at all. The two documents you have provided are both valid to be stored in MongoDB in the same database (I'm interpreting your example as an array of two documents that are both stored directly in a collection together).