Copy first array value to another field in MongoDB - mongodb

I have an old list of products that store the descriptions in an array at index [0]. The model is set up as a string. So my plan is to extract that value and add it to a temporary field. Step 2 would be to take that value and copy it to the original field.
This is the 'wrong' product I want to fix.
{_id : 1 , pDescription : ['great product']},
{_id : 2 , pDescription : ['another product']}
All I want to is to change the array to a string like this:
{_id : 1 , pDescription : 'great product'},
{_id : 2 , pDescription : 'another product'}
I have tried this to create the temporary description:
Products.aggregate([
{
$match: {
pDescription: {
$type: "array"
}
}
},
{
$set: {
pDescTemp: {
$first: "$pDescription"
}
}
}
]).exec((err, r) => {
// do stuff here
});
The command works fine without the $first command.
The error reads: MongoError: Unrecognized expression '$first'
Any tips on how to fix this are appreciated!
Thanks!

I believe this is what you need to update your pDescription field to be equal to the first element of the array already stored as pDescription:
db.Products.updateMany({},
[
{
$set: {
pDescription: {
$arrayElemAt: [
"$pDescription",
0
]
}
}
}
])

Related

Mongodb- Query to check if a field in the json array exists or not

I have a JSON in MongoDB and I am trying to check if at least one of the items in the JSON doesn't contain a specific field.
{
"_id" : 12345,
"orderItems" : [
{
"itemId" : 45678,
"isAvailable" : true,
"isEligible" " false
},
{
"itemId" : 87653,
"isAvailable" : true
}
]
}
So in the above JSON, since the 2nd one under order items doesn't contain iseligible field, I need to get this _id.
I tried the below query so far, which didnt work:
db.getCollection('orders').find({"orderItems.iseligible":{$exists:false})
You can use $elemMatch to evaluate the presence of the nested key. Once that's accomplished, project out the _id value.
db.orders.find({
orderItems: {
$elemMatch: {
"isEligible": {
$exists: false
}
}
}
},
{
_id: 1
})
Here is a Mongo playground with the finished code, and a similar SO answer.

Insert date stamp into new entry into an array

In a MongoDB collection, I want to add a new object to an array which may or may not already exist, with the creation date of the object as one of the fields. Here's a barebones version of the structure of my test collection, showing the result that I want to achieve:
{
"_id" : 1,
"parent" : {
"array_1" : [
{ "key" : "value_1"
, "created": ISODate(...)
}
]
}
}
In meteor mongo, I create the parent with the following commands:
use test
db.test.insert({ _id: 1, parent: {} })
I can add a new array with the following command:
db.test.update(
{ _id: 1 }
, { $push: {
"parent.array_1": {
key: "value_1"
}
}
}
, { $currentDate:
{ "parent.array_1.$.created": true }
}
)
However, in the resulting array, the created field is not added. I need to use a second command which refers to the array in the selection query:
db.test.update(
{ _id: 1
, "parent.array_1.key": "value_1"
}
, { $currentDate:
{ "parent.array_1.$.created": true}
}
)
Is there a way to insert the created field at the same time as the array item that it belongs to, in a single command?
You are passing 3 arguments to update. The second argument is supposed to be the update, and the third is supposed to be an options object. If you want to include the create time in the array element, make sure it is in the object that you are pushing on the array. Since you are using javascript, that could be:
db.test.update(
{ _id: 1 }
, { $push: {
"parent.array_1": {
key: "value_1",
created: new Date()
}
}
}
)

Query document for record with array value of null

I have a document like this:
{
"_id" : "4mDYgt6gID",
...
"MultipleChoiceQuestions" : [
{
...
"LeadInFile" : null,
...
},
{
...
"LeadInFile" : 'some string',
...
}
],
...
}
How do I query for any documents that have a non-null value in LeadInFile?
I'm trying different things, currently something like this
db.getCollection('QuizTime:Quizzes').find({"MultipleChoiceQuestions": [{ "LeadInFile": { $ne: null}}]});
Is returning 0 records.
The current form of the query is saying:
Find documents where MultipleChoiceQuestions is [{ "LeadInFile": { $ne: null}}]
Try using dot notation; this is used to access elements of an array or fields in an embedded document. For example:
db.getCollection('QuizTime:Quizzes').find({
"MultipleChoiceQuestions.LeadinFile" : { "$ne" : null }
})

How do I use spring mongo data to query based on the position of an element in an array

I have a mongo collection "test" which contains elements like so (with the nodes array being a set and meaningful order):
"test" : {
"superiorID" : 1,
"nodes" : [
{
"subID" : 2
},
{
"subID" : 1
},
{
"subID" : 3
}
]
}
or
"test" : {
"superiorID" : 4,
"nodes" : [
{
"subID" : 2
},
{
"subID" : 1
},
{
"subID" : 3
}
]
}
I am using spring Criteria to try and build a mongo query which will return to me all elements where the 'subID' equals a user input id 'inputID' AND the 'superiorID' position is NOT before the 'inputID' (if the superior id is even in the sub ids which is not required).
So for example, if my user input was 3 I would NOT want to pull the first document but I WOULD want to pull the second document (first has a superior that exists in the nodes BEFORE the userInput node second's superior id is not equal to the user input).
I know that the $indexOfArray function exists but I don't know how to translate this to Criteria.
You can get the result you are looking for through the aggregation framework. I've made a speude query for you to show what you should be looking for. This returns
showMe = false for doc1 and showMe = true for doc2, which you could obiously match for. You do not need 2 project phases for this query, I only did that to make a working query which is also easy-ish to read. This will not be a very fast query. If you want fast queries you might want to rethink your data structure.
db.getCollection('test').aggregate([
{ "$project":
{
"superiorIndex": {"$indexOfArray" : [ "$nodes.subID","$superiorID" ]},
"inputIndex": {"$indexOfArray" : [ "$nodes.subID",3 ]},
}
},
{ "$project":
{
"showMe" :
{
$cond:
{
if: { $eq: [ "$superiorIndex", -1 ] },
then: true,
else: {$gt:[ "$superiorIndex","$inputIndex"]}
}
}
}
}
])
db.collection.find({nodes.2.subID:2}) that query will lookup 2th element subid from nodes field.

Select data where the range between two different fields contains a given number

I want to make a find query on my database for documents that have an input value between or equal to these 2 fields, LOC_CEP_INI and LOC_CEP_FIM
Example: user input a number to the system with value : 69923994, then I use this input to search my database for all documents that have this value between the range of the fields LOC_CEP_INI and LOC_CEP_FIM.
One of my documents (in this example this document is selected by the query because the input is inside the range):
{
"_id" : ObjectId("570d57de457405a61b183ac6"),
"LOC_CEP_FIM" : 69923999, //this field is number
"LOC_CEP_INI" : 69900001, // this field is number
"LOC_NO" : "RIO BRANCO",
"LOC_NU" : "00000016",
"MUN_NU" : "1200401",
"UFE_SG" : "AC",
"create_date" : ISODate("2016-04-12T20:17:34.397Z"),
"__v" : 0
}
db.collection.find( { field: { $gt: value1, $lt: value2 } } );
https://docs.mongodb.com/v3.2/reference/method/db.collection.find/
refer this mongo provide range facility with $gt and $lt .
You have to invert your field names and query value.
db.zipcodes.find({
LOC_CEP_INI: {$gte: 69923997},
LOC_CEP_FIM: {$lte: 69923997}
});
For your query example to work, you would need your documents to hold an array property, and that each item in this prop hold a 69923997 prop. Mongo would then check that this 69923997 prop has a value that is both between "LOC_CEP_INI" and "LOC_CEP_FIM" for each item in your array prop.
Also I'm not sure whether you want LOC_CEP_INI <= 69923997 <= LOC_CEP_FIM or the contrary, so you might need to switch the $gte and $lte conditions.
db.zipcodes.find( {
"LOC_CEP_INI": { "$lte": 69900002 },
"LOC_CEP_FIM": { "$gte": 69900002 } })
Here is the logic use it as per the need:
Userdb.aggregate([
{ "$match": { _id: ObjectId(session._id)}},
{ $project: {
checkout_list: {
$filter: {
input: "$checkout_list",
as: "checkout_list",
cond: {
$and: [
{ $gte: [ "$$checkout_list.createdAt", new Date(date1) ] },
{ $lt: [ "$$checkout_list.createdAt", new Date(date2) ] }
]
}
}
}
}
}
Here i use filter, because of some reason data query on nested data is not gets succeed in mongodb