So I'm using ArangoDB and got a nested data structure like the following:
doc 1 = { "a" : {
"uid": 1,
"properties":{
"meta": 0
}
}
}
doc 2 = { "a" : {
"uid": 1,
"properties":{}
}
}
I want to be able to fetch all document where uid is 1 without having to take in account the properties attribute's value.
Doing a fetch by example with { "a" : { "uid": 1 } } return nothing.
Assuming doc1 and doc2 are documents saved in a document collection docs, you can access all documents with uid=1 by filtering on the subattribute a.uid.
AQL example:
FOR doc IN docs FILTER doc.a.uid==1 RETURN doc
Related
Basically I have documents in which I have on field called "Difficulty Level" and value of this filed is between 1 to 10 for each documents.
So, I have to select random 10 or 20 documents so that in randomly selected documents , atleast 1 document should be there for each difficulty level i.e. from 1 to 10. means there should atlease one document with "Difficulty level" : 1 ,"Difficulty level" : 2 ,"Difficulty level" : 3 ............."Difficulty level" : 10.
So, How can I select documents randomly with this condition fulfilled ?
Thanks
I tried $rand operator for selecting random documents but can't getting solution for that condition.
If I've understood correctly you can try something like this:
The goal here is to create a query like this example
This query gets two random elements using $sample, one for level1 and another for level2. And using $facet you can get multiple results.
db.collection.aggregate([
{
"$facet": {
"difficulty_level_1": [
{
"$match": { "difficulty_level": 1 } },
{ "$sample": { "size": 1 } }
],
"difficulty_level_2": [
{ "$match": { "difficulty_level": 2 } },
{ "$sample": { "size": 1 } }
]
}
}
])
So the point is to do this query in a dynamic way. So you can use JS to create the object query an pass it to the mongo call.
const random = Math.floor((Math.random()*10)+1) // Or wathever to get the random number
let query = {"$facet":{}}
for(let i = 1 ; i <= random; i++){
const difficulty_level = `difficulty_level_${i}`
query["$facet"][difficulty_level] = [
{ $match: { difficulty_level: i }},
{ $sample: { size: 1 }}
]
}
console.log(query) // This output can be used in mongoplayground and it works!
// To use the query you can use somethiing like this (or other way you call the DB)
this.db.aggregate([query])
I have a mongoose schema of mixed types like so:
const user = mongoose.Schema({
...
"links" : []
...
After populating this schema, I ended up with data like so:
[
[
{
"step1": "post-url-google", // This field is unique for each entry
"step2": {
"title": "Heading 1",
"likes": 4
}
},
],
[
{
"step1": "post-url-microsoft",
"step2": {
"title": "Heading 1",
"likes": 1
}
},
{
"step1": "post-url-apple",
"step2": {
"title": "Heading 2",
"likes": 6 // I want to update this to 7
}
}
]
]
What I want to achieve is to update the "step1": "post-url-apple" field from 6 to have a likes of 7
So I tried using the User.save() function like so:
let user = await User.findOne({"_id" : "some_id"})
user.links[1].some(object => {
if (object.step1 === "post-url-apple") {
object.step2.likes = 7
(async function (){
user.save() // I also did error handling
})()
return
}
})
This method works fine and the user gets updated but it keeps throwing ParallelSaveError possibly because I am calling the save() function in parallel on the same user instance in some other parts of my code.
So I decided to use the User.findOneAndUpdate() method, but my queries keep failing when using the mongodb dot notation $[<identifier>], obviously because I don't know how to use it properly.
Like so:
let update = {
"$set" : {
"links.$[index1].$[index2].step2.likes" : 7,
}
}
let conditions = {
arrayFilters : [
{"index1" : 1},
{"index2.step1" : "post-url-apple"}
]
}
try {
let result = await Users.findOneAndUpdate({"_id" : "some_id"}, update, conditions)
console.log(result)
} catch (err) {
console.log(err)
}
For all good reasons, I'm not hiting the catch block but the update was equally not successful
How do I achieve updating the "step1": "post-url-apple" likes field to 7 using findOneAndUpdate?
Thank you.
In arrayFilters you should define the conditions to be applied to all the array elements, not the index
If you are sure, you always update the second array element (index = 1) of the outer array, then you can use the dot notation for the outer array, and for the inner array you can use the array filters to get the element that has step1 = 'post-url-apple'
your code may look something like that
let update = {
"$set" : {
'links.1.$[item].step2.likes': 7 // here we used links.1 to access the second element of the outer array
}
}
let conditions = {
arrayFilters : [
{ 'item.step1' : 'post-url-apple' } // item here is the element in the inner array that has step1 = post-url-apple
]
}
then do your update query
hope it helps
My data model looks roughly like this:
data = {
...
parameters: [{type:Schema.Types.mixed}],
...
}
If i now insert a document into the database,
doc = {
...
parameters:[{"foo":"bar"}],
...
}
i can query it via the "parameters" key:
db.dataset.find({"parameters":[{"foo":"bar"}]},function(doc){
...
})
and get back the expected document. However if "parameters" contains more than one key, for example
doc = {
...
parameters:[{"foo":"bar","ding":"dong"}]
...
}
i cant find it anymore. Why?
It is because the query cannot match any documents where the array field parameters has the exact array object as its value [{"foo": "bar", "ding": "dong"}]. To demonstrate this, let's insert a couple of sample documents in a collection:
/* 0 */
{
"_id" : ObjectId("551d777fcfd33f4e2a61e48f"),
"parameters" : [
{
"foo" : "bar"
}
]
}
/* 1 */
{
"_id" : ObjectId("551d777fcfd33f4e2a61e490"),
"parameters" : [
{
"foo" : "bar",
"ding" : "dong"
}
]
}
Querying this collection for parameters array with this object array [{"foo":"bar"}] will bring the document with "_id" : ObjectId("551d777fcfd33f4e2a61e48f"). However, if you change your query object to use $elemMatch then it will bring both documents:
db.collection.find({"parameters": { "$elemMatch": { "foo": "bar" } }});
I need to create a view that lists the values for an attribute of a doc field.
Sample Doc:
{
"_id": "003e5a9742e04ce7a6791aa845405c17",
"title", "testdoc",
"samples": [
{
"confidence": "high",
"handle": "joetest"
}
]
}
Example using that doc, I want a view that will return the values for "handle"
I found this example with the heading - Get contents of an object with specific attributes e.g. doc.objects.[0].attribute. But when I fill in the attribute name, e.g. "handle" and replace doc.objects with doc.samples, I get no results:
Toggle line numbers
// map
function(doc) {
for (var idx in doc.objects) {
emit(doc.objects[idx], attribute)
}
}
That will create an array of key-value-pairs where the key is alway the value of handle. Replace null with a value you want e.g. doc.title. If you want to get the doc attached to every row use the query parameter ?include_docs=true while requesting the view.
// map
function (doc) {
var samples = doc.samples
for(var i = 0, sample; sample = samples[i++];) {
emit(sample.handle, null)
}
}
Like this ->
function(doc) {
for (var i in doc.samples) {
emit(doc._id, doc.samples[i].handle)
}
}
It will produce a result based on the doc._id field as the key. Or, if you want your key to be based on the .handle field you reverse the parameters in emit so you can search by startKey=, endKey=.
I am learning couchdb, so I have a very basic questions. Suppose I have a couch database called email where documents look like:
{
"_id": "fe7759fdf36t",
"status": "sent",
"sent_at": 1357151443,
}
{
"_id": "ewrwe4a38d2353",
"status": "failed",
"sent_at": 2347151421,
}
{
"_id": "f4559fjffd2353",
"status": "sent",
"sent_at": 11715154,
}
I want to create two views
1) Retrieve all documents where status = sent
2) Retrieve all documents where status = failed and sent_at > 11715157
3) Retrieve all documents sorted by sent_at descending/ascending and status = sent
For (1), I wrote,
{
"_id": "_design/sentdoc",
"_rev": "2-dd88de7196c06eed41d2d83a958f0388",
"views": {
"query": {
"map": "function(doc) { if(doc.status == 'sent') {emit(doc_id, doc);} }"
}
}
}
I guess I am doing something wrong there, so it is not working. Can anyone suggest how to write all these three views?
Create a view like this
function(doc){
emit([doc.status, doc.sent_at], doc);
}
Query #1
Try these params in your curl statement (or Ruby library or whatever)
startkey = ["sent"]
endkey = ["sent",{}]
Query #2
startkey = ["failed", 11715157]
endkey = ["failed", {}]
Query #3
startkey = ["sent"]
endkey = ["sent", {}]
descending = true
I've not tested this, but should point you in the right direction.