Mongo DB: Append a value to a nested array - node.js

I think there might be better ways to store data but the app I am working on has some data stored like this.
I have a document with nested arrays. In this particular example, would it be possible to append a new element "value3" to an array inside products whose "productId" matches the condition. So, basically look for productId and append "value3" to the array which has matching "productId".
I am just learning about MongoDB so if you can provide some suggestions for changing schema, even that would be very helpful.
P.S. Not sure if it helps but I am using node.js
{"_id":
{"$oid":"601baf0e5c307422c0fa958c"},
"sale":"Test Sale",
"products":[
[
["productId","value1","value2"],
["productId","value1","value2"]
],
[
["productId","value1","value2"],
["productId","value1","value2"]
],
[
["productId","value1","value2"],
["productId","value1","value2"]
]
],
"collectionProducts":["id","id","id"]
}

Maybe something like this:
db.store.update({},{$push:{"products.$[].$[k]":"value3"}},{ arrayFilters: [{ k:'productId' }]})

Related

Create and query mango index on unknown object key in CouchDB

I have the following object:
{
"roleAttribution": {
"15497490976600-51042": {
"teams": [
"e5abb1e962e11a84ff0e41e99103cd90"
],
"persons": [
"15124323582330-17269"
]
}
},
"type": "link",
}
And need to index/query the teams array. The problem is the roleAttribution keys are unpredictable.
Is there a way to index and query all possible keys of the object up to the teams array?
At this point, CouchDB does not support a good way to just index arrays. (https://issues.apache.org/jira/browse/COUCHDB-2867). You would need to create a view for that. If you would like to query documents based on the values of team array, you would need to iterate over the array in view map function and emit all the values there. More info about the views here http://guide.couchdb.org/draft/views.html

How to retrieve a subset of fields from array of objects using the Couchbase sub-document API?

I am trying to write a lookup which returns an array from a document and skipping some fields:
{
"id": 10000,
"schedule": [
{
"day": 0,
"flight": "AF198",
"utc": "10:13:00"
},
{
"day": 0,
"flight": "AF547",
"utc": "19:14:00"
},
...
]
}
I would like to get all schedule items but only the flight properties. I want to get something like this:
[
{
"flight: "AF198"
},
{
"flight: "AF547"
},
...
]
bucket.lookupIn(key).get("schedule.flight") doesn’t work. I tried "schedule[].flight", "schedule.$.flight" It seems I always need to know the index.
I saw that this is possible with N1QL.
Couchbase - SELECT a subset of fields from array of objects
Do you guys know how to do this with the Subdocument API? Sorry if it is a trivial question. I just cannot find an example on
https://developer.couchbase.com/documentation/server/current/sdk/subdocument-operations.html
Couchbase Subdocument requires the full path, it does not support expansion. In this case it needs to know the index of the array. There are a few other options:
If every path is known, then you could chain all of the subdocument gets. A total of 16 paths can be got at once:
bucket.lookupIn(key).get("schedule[0].flight").get(schedule[1].flight")
Get the parent object and filter on the application side:
bucket.lookupIn(key).get("schedule")
As mentioned in the question, use N1QL.

SELECT single field from embedded array in azure documentDB

I have a documentDB collection that looks like this sample:
{
"data1": "hello",
"data2": [
{
"key": "key1",
"value": "value1"
},
{
"key": "key2",
"value": "value2"
}
}
In reality the data has a lot of other fields and the embedded array has some fields where the data is quite large. I need to query the data and I care about the small "key" field in the data2 array but I do not need the large "value". I am finding returning all the value data is causing performance problems, but if I exclude the array data from the SELECT all together it is fast (so the data size is the issue).
I cannot figure out a way to return only the "key" but exclude the "value" in the embedded array.
I basically want SELECT r.data1, r.data2.key and to have it return as:
{
"data1": "hello",
"data2": [
{
"key": "key1"
},
{
"key": "key2"
}
}
but it doesn't seem possible to SELECT r.data2.key because it is in an array
A JOIN will cause it to return a copy of each document for each "data2" array element, which does not work for me. My only other option would be to migrate the data and put the data I want into its own array so I can select the whole object.
Is this possible some how that I have not been able to figure out?
Mike,
As you have surmised, this is not possible without a custom UDF until DocumentDB supports sub-queries. If you would like to go down that route, see the following answer for an example of how the UDF may have to look:
DocumentDB Sub Query
Good luck!

How to populate through array in mongoose

I have a record like this,
"student" : [
ObjectId("5850e76196d4de3c1f4a0618"),
ObjectId("5850da3e7f3ff224767c196c")
],
I tried,
Classroom.findById(id).populate('student')
Can anyone suggest me that, how can I populate through this array.

mongoose exclude field in array

I have something like:
Schema Subdocument
name: String
data: Mixed
Schema Stuff
documents: [Subdocument]
Now, in my API there are two endpoints, one for the Subdocument and another for Stuff. When I want to get a Subdocument I need to contain the data field, but when I want to get Stuff, I want to show the name of those subdocuments, but I don't want to show the data field because is quite large and it won't be used.
So, to keep things clear, data is not private. It's just that I don't want it to be shown when I get it from Stuff
I tried by doing:
Stuff.findById(id)
.populate("documents")
.populate("-documents.data")
but that doesn't work... I'm getting the Stuffwith the Subdocumentcontaining the name and data. I feel like i'm missing to tell mongoose when I call populate("-documents.data") that documents is an array and I want to exclude the data field for each element in this array.
edit: Sorry the Schema I provided was not for my case. In my case it was not embedded, but a reference, like so:
Schema Subdocument
name: String
data: Mixed
Schema Stuff
documents: [{
type: Schema.Types.ObjectId,
ref: 'Subdocument'
}]
Assuming subDocument is not embedded and using as "ref" as you say populate is working but data part is not included:
Stuff.findById(id).populate( { "path" : "documents", "select" : "-data" })
Your documents have an "embedded" schema, so populate is not used here, it is used only for "referenced" schemas where the other objects are in another collection.
Fortunately with "embedded" there is an easy way using projection:
Stuff.findById(id,{ "documents.name": 1 },function(err,results) {
})
With results like
{ "documents": [{ "name": "this" },{ "name": "that" }] }
Or with .aggregate() and the $map operator:
Stuff.aggregate(
[
{ "$match": { "_id": ObjectID(id) } },
{ "$project": {
"documents": {
"$map": {
"$input": "$documents",
"as": "el",
"in": "$$el.name"
}
}
}}
],function(err,results) {
}
)
That will just tranform into an array of "only" the name "values", which is different to the last form.
{ "documents": ["this", "that"] }
Note, if using .aggregate() you need to properly cast the ObjectId as the autocasting from mongoose schema types does not work in aggregation pipeline stages.

Resources