I'm transitioning to ArangoDB for its power as a graph database and am struggling with the simple stuff.
If I have a document...
{ _id:'1234', tags:['apple','orange'] }
how can I update it to push or pull a value from the array? I would expect the syntax to be something like this, but didn't find anything in the docs...
collection.update({ _id:'1234' },{ tags:pull('mango') })
collection.update({ _id:'1234' },{ tags:push('avocado') })
Thank you!
You achieve this with AQL. For example
FOR c in collection UPDATE c WITH { tags : PUSH(c.tags, 'avocado')} IN collection
https://docs.arangodb.com/3.3/AQL/Operations/Update.html
Related
I'm trying to do a simple query where some collection data is returned. I want to filter out the _id field in the results.
From my understanding (based on the documentation) the syntax to do so should look like this:
myCollection.findOne(
{ name: hostName },
{ $project: { _id: 0 } }
)
However when I do this the filter has not been applied, e.g.:
{
_id: XXXXXXXXXXXXXXXXXXXX,
name: 'the name',
...
}
Can anybody point me in the right direction?
There are other options for $project. Below one provides the data without _id
myCollection.findOne({ name: hostName }, { '_id': 0 },(err,res)
In case anyone else comes across this, it turns out that the documentation is inaccurate and does not reflect the current state of the SDK.
For reference, see this GitHub Issue where it was confirmed by a Realm dev: https://github.com/realm/realm-js/issues/3275
Context:
My database has two collections: "Users" and "Files".
Sample document from "Users" collection:
{
"username":"Adam",
"email":"adam#gmail.com",
"IdFilesOwned":[1,3],
}
As you can see, Adam currently owns two files on the server. Their ids are 1 and 3.
Sample documents from "Files" collection:
{
"fileId":1,
"name":"randomPNG.png"
}
{
"fileId":2,
"name":"somePDF.pdf"
}
{
"fileId":3,
"name":"business.pdf"
}
As you can see, I have three documents on my server, each document having an id and some metadata.
Now, Adam wants to see all the files that he owns, and their metadata. The way i would implement this, is:
1.Lookup the array of file ids that Adam owns.
2.Have node.js run through each id (using a for each loop), and query the metadata for each id.
The problem is that nodejs will make multiple queries (1 query per id). This seems very inefficient. So my question is if there is a better way to implement this?
You can use the $in operator find more info here
So it will look something like this.
db.collection('files').find({ fileId: { $in: [<value1>, <value2>, ... <valueN> ] } })
This is more efficent than lookup for sure. Good luck.
I don't have much experience using the driver directly, but you should be able to do the equivalent of the following
db.users.aggregate([
{
$lookup: {
from: "files",
localField: "IdFilesOwned",
foreignField: "fileId",
as: "files"
}
}
]);
So I have an object using a dictionary to store products that a user has added to the cart in a shopping cart application. I am taking is object and attempting to insert into mongoDB with zero luck.
The piece of data I am attempting to insert looks like this:
products: '{"rJUg4uiGl":{"productPrice":"78.34","count":2},"BJ_7VOiGg":{"productPrice":"3","count":2}}' }
My process of attempting to insert it into mongoDB looks like this:
db.orders.insert("products":{"rJUg4uiGl":{"productPrice":"78.34","count":2},"BJ_7VOiGg":{"productPrice":"3","count":2}});
Currently with this approach I get the following error:
2016-12-15T18:11:43.862-0500 E QUERY [thread1] SyntaxError: missing ) after argument list #(shell):1:27
Which is implying there is some sort of a formatting issue with inserting it. I have moved quotation marks and parenthesis around plenty, simply to either get the above error, or a ... response from mongoDB implying that it is waiting for me to do something more to fix what exactly is causing an error.
Any chance anyone could help give some guidance in the best way to store this object in mongoDB?
My true question feels that it should have been in regards to the mongoose schema that would be used in order to store this data format. I hoped that getting how to initially insert it into mongodb was going to be enough but the way the data is being saved has me a bit confused. I know this is a bit of an awful question but could I get any assistance with setting up my schema for this as well?
"products" : {
"rJUg4uiGl" : {
"productPrice" : "78.34",
"count" : 2
},
"BJ_7VOiGg" : {
"productPrice" : "3",
"count" : 2
}
}
This is what the data looks like when it is stored in mongo. I think what is confusing me on how to set up is the "rJUg4uiGl" portion of the data. I am un-sure of how exactly that is suppose to look in mongoose schema. Here are a few of my rather poor attempts:
products: {
productId: {
productPrice: Number,
count: Number
}
}
Above simply doesn't store anything in the database
products: {
productId: [{
productPrice: Number,
count: Number
}]
}
Above gives:
"products" : {
"productId" : [ ]
}
Again, I know that this is quite specific but any help at all would be extremely appreciated.
Need to wrap your insert data in {}
db.orders.insert({"products":{"rJUg4uiGl":{"productPrice":"78.34","count":2},"BJ_7VOiGg":{"productPrice":"3","count":2}}});
I am trying to figure out the most efficient way to find and populate documents some of which have references to another collection and some don't.
Example:
var collectionA={
{
"topic":"TopicA",
"text";"TextA")
},
{
"topic":"Topic1",
"text":"Text1"}
}
}
var collectionB={
{
"topic":"TopicB",
"text":"TextB"
"reference":["id","id"]
},
{
"topic":"Topic2",
"text":"Text2"
"reference":[]
}
}
and I have a request as follows which allows me to identify the documents I want:
req.body={"topic":["TopicA","TopicB"]}
What is the most efficient way to find the relevant documents and populate them to provide a fully populated result, in the fewest number of database calls as possible:
{"topic":"TopicA","text":"TextA"},
{"topic":"TopicB","text":"TextB","reference":[{populated document}
{populated document}]},
I am trying to use something like:
collections.find({"topic": $in req.body.top}, function(err,result){
collections.populate(result,{path:'references'}, function (err,result){
//do something
});
})
Is this on the right track?
Your help is greatly appreciated.
In order to reference other documents in mongoose you need to use Population.
If you want to reference a topic by id you would need to have something like the following in your schema: { type: Schema.Types.ObjectId, ref: 'collectionA' }
How can I query a Mongo collection using Mongoose to find all the documents that have a specific relation between two of their own properties?
For example, how can I query a characters collections to find all those characters that have their currentHitPoints value less than their maximumHitPoints value? Or all those projects that have their currentPledgedMoney less than their pledgeGoal?
I tried to something like this:
mongoose.model('Character')
.find({
player: _currentPlayer
})
.where('status.currentHitpoints').lt('status.maximumHitpoints')
.exec(callback)
but I am getting errors since the lt argument must be a Number. The same goes if I use $.status.maximumHitpoints (I was hoping Mongoose would be able to resolve it like it does when doing collection operations).
Is this something that can be done within a Query? I would expect so, but can't find out how. Otherwise I can filter the whole collection with underscore but I suspect that is going to have a negative impact on performance.
PS: I also tried using similar approaches with the find call, no dice.
MongoDB 3.6 and above supports aggregation expressions within the query language:
db.monthlyBudget.find( { $expr: { $gt: [ "$spent" , "$budget" ] } } )
https://docs.mongodb.com/manual/reference/operator/query/expr/
Thanks to Aniket's suggestion in the question's comments, I found that the same can be done with Mongoose using the following syntax:
mongoose.model('Character')
.find({
player: _currentPlayer
})
.$where('this.status.currentHitpoints < this.status.maximumHitpoints')
.exec(callback)
Notice the $where method is used instead of the where method.
EDIT: To expand on Derick's comment below, a more performance sensitive solution would be to have a boolean property inside your Mongoose schema containing the result of the comparison, and update it everytime the document is saved. This can be easily achieved through the use of Mongoose Schema Plugin, so you would have something like:
var CharacterSchema = new mongoose.Schema({
// ...
status: {
hitpoints: Number,
maxHitpoints: Number,
isInFullHealth: {type: Boolean, default: false}
}
})
.plugin(function(schema, options) {
schema.pre('save', function(next) {
this.status.isInFullHealth = (this.status.hitPoints >= this.status.maxHitpoints);
next();
})
})
mongoose.model('Character')
.find({
player: _currentPlayer, $expr: { $lt: ['$currentHitpoints', '$maximumHitpoints'] }
})
This above query means find the record which has currentHitpoints less than maximumHitpoints
Starting in MongoDB 5.0, the $eq, $lt, $lte, $gt, and $gte comparison operators placed in an $expr operator can use an index on the from collection referenced in a $lookup stage.
Example
The following operation uses $expr to find documents where the spent amount exceeds the budget:
db.monthlyBudget.find( { $expr: { $gt: [ "$spent" , "$budget" ] } } )