Insert numbers into mongo-db collection - arrays

I am currently learning Mongo DB and trying to insert numbers into my "numbers" collection (in mongo command shell).
//This works :
db.numbers.insertMany([{"number":1},{"number":2}]);
//This doesn't
db.numbers.insertMany([1,2,3,4,5,6]);
(1) Does that mean that number is not a valid document or I am missing a very basic concept ?
(2) Why Mongo-db is not assigning Object-ID to numbers automatically in this case ?

//actual output from Mongoshell version 4.2.6 command line
> db.numbers.insertMany([{"number":1},{"number":2}]);
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5f79fa89d04cd9e2b3acbf03"),
ObjectId("5f79fa89d04cd9e2b3acbf04")
]
}
> db.numbers.find();
{ "_id" : ObjectId("5f79fa89d04cd9e2b3acbf03"), "number" : 1 }
{ "_id" : ObjectId("5f79fa89d04cd9e2b3acbf04"), "number" : 2 }
> db.numbers.insertOne({number:[1,2,3,4,5,6]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5f79fa9ed04cd9e2b3acbf05")
}
> db.numbers.find();
{ "_id" : ObjectId("5f79fa89d04cd9e2b3acbf03"), "number" : 1 }
{ "_id" : ObjectId("5f79fa89d04cd9e2b3acbf04"), "number" : 2 }
{ "_id" : ObjectId("5f79fa9ed04cd9e2b3acbf05"), "number" : [ 1, 2, 3, 4, 5, 6 ] }
>

Related

Remove duplicates from MongoDB 4.2 data base

I am trying to remove duplicates from MongoDB but all solutions find fail.
My JSON structure:
{
"_id" : ObjectId("5d94ad15667591cf569e6aa4"),
"a" : "aaa",
"b" : "bbb",
"c" : "ccc",
"d" : "ddd",
"key" : "057cea2fc37aabd4a59462d3fd28c93b"
}
Key value is md5(a+b+c+d).
I already have a database with over 1 billion records and I want to remove all the duplicates according to key and after use unique index so if the key is already in data base the record wont insert again.
I already tried
db.data.ensureIndex( { key:1 }, { unique:true, dropDups:true } )
But for what I understand dropDups were removed in MongoDB > 3.0.
I tried also several of java script codes like:
var duplicates = [];
db.data.aggregate([
{ $match: {
key: { "$ne": '' } // discard selection criteria
}},
{ $group: {
_id: { key: "$key"}, // can be grouped on multiple properties
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}},
{ $match: {
count: { "$gt": 1 } // Duplicates considered as count greater than one
}}
],
{allowDiskUse: true} // For faster processing if set is larger
).forEach(function(doc) {
doc.dups.shift(); // First element skipped for deleting
doc.dups.forEach( function(dupId){
duplicates.push(dupId); // Getting all duplicate ids
}
)
})
and it fails with:
QUERY [Js] uncaught exception: Error: command failed: {
“ok“: 0,
“errmsg“ : “assertion src/mongo/db/pipeline/value.cpp:1365“.
“code“ : 8,
“codeName" : “UnknownError“
} : aggregate failed
I haven't change MongoDB settings, working with the default settings.
This is my input collection dups, with some duplicate data (k with values 11 and 22):
{ "_id" : 1, "k" : 11 }
{ "_id" : 2, "k" : 22 }
{ "_id" : 3, "k" : 11 }
{ "_id" : 4, "k" : 44 }
{ "_id" : 5, "k" : 55 }
{ "_id" : 6, "k" : 66 }
{ "_id" : 7, "k" : 22 }
{ "_id" : 8, "k" : 88 }
{ "_id" : 9, "k" : 11 }
The query removes the duplicates:
db.dups.aggregate([
{ $group: {
_id: "$k",
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}},
{ $project: { k: "$_id", _id: { $arrayElemAt: [ "$dups", 0 ] } } }
] )
=>
{ "k" : 88, "_id" : 8 }
{ "k" : 22, "_id" : 7 }
{ "k" : 44, "_id" : 4 }
{ "k" : 55, "_id" : 5 }
{ "k" : 66, "_id" : 6 }
{ "k" : 11, "_id" : 9 }
As you see the following duplicate data is removed:
{ "_id" : 1, "k" : 11 }
{ "_id" : 2, "k" : 22 }
{ "_id" : 3, "k" : 11 }
Get the results in an array:
var arr = db.dups.aggregate([ ...] ).toArray()
The arr has the array of the documents:
[
{
"k" : 88,
"_id" : 8
},
{
"k" : 22,
"_id" : 7
},
{
"k" : 44,
"_id" : 4
},
{
"k" : 55,
"_id" : 5
},
{
"k" : 66,
"_id" : 6
},
{
"k" : 11,
"_id" : 9
}
]

Pushing objects on a specific multidimensional mongoDb collection

i'm fairly new to the mongoDb query language and I'm struggeling with following scenario.
We have a multidimensional dataset that is comprised of:
n users
n projects for each users
n time_entries for each project
What I am trying to achieve is: I would like to push/update a time_entry of a specific project using a collection.update.
Note each pid should be unique for a user
The collection structure I am using looks as follows:
{
"_id" : ObjectId("5d6e33987f8d7f00c063ceff"),
"date" : "2019-01-01",
"users" : [
{
"user_id" : 1,
"projects" : [
{
"pid" : 1,
"time_entries" : [
{
"duration" : 1,
"start" : "2019-08-29T09:54:56+00:00"
}
]
},
{
"pid" : 2,
"time_entries" : []
}
]
},
{
"user_id" : 2,
"projects" : [
{
"pid" : 3,
"time_entries" : []
}
]
}
]
}
I'm currently able to update all projects of a given user using:
"users.$.projects.$[].time_entries"
yet I'm not able to target a specific project, due to the fact the structure contains 2 nesting levels and using multiple $ positional operator is not yet permitted in MongoDb.
"users.$.projects.$.time_entries"
Below is my full query example:
db.times.update(
{ 'users' : { $elemMatch : { 'projects' : { $elemMatch : { 'pid' : 153446871 } } } } },
{ "$push":
{
"users.$.projects.$[].time_entries":
{
"duration" : 5,
"start" : "2019-08-29T09:54:56+00:00"
}
}
}
);
Are there other ways to achieve the same result?
Should I flatten the array so I only use 1 $ positional operator?
Are there other methods to push items on a multidimensional array?
Should this logic be handled on a code level and not a Database level?
You'll need to use the Positional Filtered Operator to achieve that:
db.times.update(
{},
{
$push: {
"users.$[].projects.$[element].time_entries":{
"duration" : 5,
"start" : "2019-08-29T09:54:56+00:00"
}
}
},
{
arrayFilters: [{"element.pid":1}],
multi: true
}
)
This query will push data to the array time_entries for every pid = 1 it finds.
This will give you the result below:
{
"_id" : ObjectId("5d6e33987f8d7f00c063ceff"),
"date" : "2019-01-01",
"users" : [
{
"user_id" : 1,
"projects" : [
{
"pid" : 1,
"time_entries" : [
{
"duration" : 1,
"start" : "2019-08-29T09:54:56+00:00"
},
{
"duration" : 5.0,
"start" : "2019-08-29T09:54:56+00:00"
}
]
},
{
"pid" : 2,
"time_entries" : []
}
]
},
{
"user_id" : 2,
"projects" : [
{
"pid" : 3,
"time_entries" : []
}
]
}
]
}

Access MongoDB Array of Embedded Documents in PHP

Hi I'm trying to reach embedded document inside this array:
"_id" : 0,
"name" : "Sykes",
"orders" : [
{
"invoiceNumber" : 788,
"cart" : [
{
"item" : 0,
"pkgId" : 3,
"qty" : 10
}
]
},
{
"invoiceNumber" : 801,
"cart" : [
{
"item" : 1,
"pkgId" : 1,
"qty" : 8
}
]
}
I've tried this:
db.customer.find({_id:1},{'orders.invoiceNumber':1,_id:0}).pretty()
I need to convert this command to PHP. Any help please?

How to retrieve distinct keys inside an object in MongoDB

I have this in MongoDB:
{ "_id" : ObjectId("58fb35531eb5df245d5d434f"), "name" : "d1.html", "indexation" : { "Citroen" : 1, "color" : 1, "Marca" : 1, "rojo" : 1 } }
{ "_id" : ObjectId("58fb35531eb5df245d5d4350"), "name" : "d2.html", "indexation" : { "blancos" : 1, "ocasión" : 1, "Madrid" : 1, "Coches" : 1, "rojo" : 1, "coches" : 1 } }
{ "_id" : ObjectId("58fb35531eb5df245d5d4351"), "name" : "d3.html", "indexation" : { "rojos" : 1, "Ocasión" : 1, "marcas" : 1, "Madrid" : 1, "blancas" : 1, "autos" : 1, "de" : 1 } }
You can see an image containing the above:
And I would like to get the distinct keys inside the object "indexation" in each document.
The result I woul like to get is: ["Citroen", "color", "Marca", "rojo", "blancos", "ocasión", "Madrid", "Coches", "coches", "rojos", "Ocasión", "marcas", "blancas" "autos", "de"].
I'm trying with distinct ("indexation") but I get the whole indexation...
Could you explain to me what do I have to do to get what I want, please?
You can use new $objectToArrray in 3.4.4 version to convert all key & value pair into document arrays followed by $unwind & $group with $addToSet to get distinct keys
db.collection.aggregate([{$project: {indexation: {$objectToArray: "$indexation"}}}, {$unwind:"$indexation"}, {$group:{_id:null, keys:{$addToSet:"$indexation.k"}}}])
For lower version you've to update indexation to look like below and and use
db.collection.distinct("indexation.k")
{ "_id" : ObjectId("58fb35531eb5df245d5d434f"), "name" : "d1.html", "indexation" : [{ "k" : "Citroen", "v" : 1 }, { "k" : "Marca", "v" : 1 }]}

Find documents matching multiple fields in an object array in MongoDB

Let's say I have an array of objects (let us call that array A) and I need a query to find a collection in MongoDB for all documents matching one of it's fields to one of the properties of object 1 in array A and another field to some other property in the same object in array A.
The documents do not have all the properties that the objects in array A have.
To make things clear...
Array A would look something like this...
[{
id_bus:1,
id_bus_variation:13,
....
},{
id_bus:2,
id_bus_variation:184,
....
},{
id_bus:3,
id_bus_variation:13,
....
}]
The documents in my database include those two properties and I need to match those two at the same time. For example, I need to find in my database the docs that have id_bus == 1 and id_bus_variation == 13, and also the ones that have id_bus == 2 and id_bus_variation == 184 but not the ones that id_bus == 4 and id_bus_variation == 13.
I really don't have any idea of how to do this using a single query, the only way around it I found is to go through array A and execute a query for each of it's elements, matching all the fields I need, but that doesn't seem efficient.
It sounds like you want to match the structure of a subdocument in an array to one of many possible structures specified by an array. I'll give an example of how to do this in the mongo shell:
> db.test.insert({
"_id" : 0,
bus : [
{ "id_bus" : 1, "id_bus_variation" : 1 },
{ "id_bus" : 2, "id_bus_variation" : 2 },
{ "id_bus" : 3, "id_bus_variation" : 3 }
]
})
> db.test.insert({
"_id" : 1,
bus : [
{ "id_bus" : 1, "id_bus_variation" : 3 },
{ "id_bus" : 2, "id_bus_variation" : 2 },
{ "id_bus" : 3, "id_bus_variation" : 1 }
]
})
> db.test.insert({
"_id" : 2,
bus : [
{ "id_bus" : 1, "id_bus_variation" : 1 },
{ "id_bus" : 2, "id_bus_variation" : 3 },
{ "id_bus" : 3, "id_bus_variation" : 2 }
]
})
If we want to return all documents where (id_bus = 2 and id_bus_variation = 3) or (id_bus = 3 and id_bus_variation = 3), as specified in an array
> var match = [{ "id_bus" : 2, "id_bus_variation" : 3 }, { "id_bus" : 3, "id_bus_variation" : 3 }];
We can construct the query programmatically:
> var query = { "$or" : [] }
> for (var i = 0; i < match.length; i++) {
query["$or"].push({ "bus" : { "$elemMatch" : match[i] } });
}
> db.test.find(query, { "_id" : 1 }) // just get _id's for easy reading
{ "_id" : 0 }
{ "_id" : 2 }
We get the expected results.
I don't know if I understand your Question.
Your collection could be like
{
"_id" : ObjectId("53de54c1560b7815e123792f"),
"bus" : [
{
"id_bus" : 1,
"id_bus_variation" : 13
},
{
"id_bus" : 2,
"id_bus_variation" : 184
},
{
"id_bus" : 3,
"id_bus_variation" : 13
}
]
}
And you want retrieve the document only if id_bus and id_bus_variation are "true"
You can try it
db.stack.find({$and:[{ "bus.id_bus" : 1,"bus.id_bus_variation" : 13},{"bus.id_bus" : 2,"bus.id_bus_variation" : 184}]})
and retrieve the Document only if bus.id_bus and bus.id_bus_variation are in Document.
For Example
db.stack.find({$and:[{ "bus.id_bus" : 1,"bus.id_bus_variation" : 13},{"bus.id_bus" : 2,"bus.id_bus_variation" : 184},{"bus.id_bus":4}]})
you haven't any result.
If you want exactly the element inside Object
db.stack.find ( { bus: { "$elemMatch" : { id_bus:1, id_bus_variation : 13} } } )
The document return only if both value are "true"

Resources