CouchDB Group Level and Key Range - nosql

Can anyone explain to me why the following doesn't work:
Assuming the following document structure:
{
"_id": "520fb089a6cb538b1843cdf3cca39a15",
"_rev": "2-f96c27d19bf6cb10268d6d1c34799931",
"type": "nosql",
"location": "AZ",
"date": "2012/03/01 00:00:00",
"amount": 1500
}
And a Map function defined like so:
function(doc) {
var saleDate = new Date(doc.date);
emit([doc.location,saleDate.getFullYear(),saleDate.getMonth()+1],doc.amount);
}
And using the built in _sum function for the reducer.
When you execute this (with group=true) you get results like this:
{"rows":[
{"key":["AZ",2012,2],"value":224},
{"key":["AZ",2012,3],"value":1500},
{"key":["WA",2011,12],"value":1965},
{"key":["WA",2012,1],"value":358}
]}
Now if you change the query to something like this:
http://127.0.0.1:5984/default/_design/nosql/_view/nosql_test?group_level=2
You get results like this:
{"rows":[
{"key":["AZ",2012],"value":1724},
{"key":["WA",2011],"value":1965},
{"key":["WA",2012],"value":358}
]}
So with that in mind if I wanted to find out all sales in 2011 for "WA" could I not execute something like this:
http://127.0.0.1:5984/default/_design/nosql/_view/nosql_test?group_level=2&key=["WA",2011]
This example has been taken from the useful videos over at NoSQL tapes.
http://nosqltapes.com/video/understanding-mapreduce-with-mike-miller

You always need to give a range of keys, because filtering is done on map's results, not on reduce.
For example, the following parameters should work (if properly url-encoded):
?group_level=2&startkey=["WA",2011]&endkey=["WA",2011,{}]
You can read about view collation to understand how it works.

Related

Mongodb use foreach on query and update results its results

I have a mongo collection where a field is supposed to point to another document's id in the same collection, but instead it is pointing to its "number". I need to perform an update on them but I'm having some problems on forming the query. Could you help me?
The structure of the document is like this:
{
"_id": "269410e2-cebf-40f1-a81f-fdce34185cdc",
"number": 1471,
"alternativeLocationId": "9871",
"locationType": "DUMMY"
},
{
"_id": "2945b24a-b82f-45a9-ad06-a884379b5597",
"number": 9871,
"locationType": "MAIN"
}
So as asked, I'd need to make document with number 1471 "alternativeLocationId" to be "2945b24a-b82f-45a9-ad06-a884379b5597" instead of 9871 (Note that the referenced documents are not locationType "DUMMY" nor have this alternativeLocationId field).
The query I've done so far goes like this, but when executed its not doing any changes:
db.location.find({alternativeLocationId: {$exists:true}}).forEach(
function (loc) {
var correctLocation = db.location.findOne({number: loc.alternativeLocationId});
db.location.update(
{_id: loc._id},
{$set: {alternativeLocationId: correctLocation._id} }
);
}
);
As mentioned by user20042973 the issue was the type mismatch between alternativeLocationId and locationNumber, after converting the value to int when looking for it, it works perfectly.

get the particular field value from mongodb

In mongodb i saved document like this.
"Angela_Merkel": {
"birthPlace": "Hamburg,West_Germany",
"thumbnail": "http://commons.wikimedia.org/wiki/Special:FilePath/Angela-Merkel-2014.jpg?width=300",
"almaMater": "Leipzig_University",
"birthDate": "1954-07-17",
"spouse": "Joachim_Sauer"
}
There are many person's information like this way. Now if I want to get all the information of "Angela_Merkel" or only a particular like "birthdDate" of "Angela_Merkel" then what will be the query?
Like chridam says would be more practical that you refactor your documents like this:
{"name": "Angela_Merkel",
"birthPlace": "Hamburg,West_Germany",
"thumbnail": "http://commons.wikimedia.org/wiki/Special:FilePath/Angela-Merkel-2014.jpg?width=300",
"almaMater": "Leipzig_University",
"birthDate": "1954-07-17",
"spouse": "Joachim_Sauer"
}
Inside the "people" collection (Its a convention name the collections as plurals, beeing a set of documents)
Then you could do:
db.people.find({"name":"Angela Merkel"},{"_id":0," "birthdDate":1 })
To get:
{"birthDate": "1954-07-17"}
Anyway you can get with your document what you want this way:
"birthDate":
db.person.find({"Angela_Merkel.birthDate": "1954-07-17"})
or all the info:
db.person.find({"Angela_Merkel": { $exists: true}})
But doesn't have much sense do it this way.
PD: Edited to include last part.

MongoDB - Manual Referencing Without Application

I understand Manual referencing being, one document containing the reference to another.
As in the MongoDB's documentation:
original_id = ObjectId()
db.places.insert({
"_id": original_id,
"name": "Broadway Center",
"url": "bc.example.net"
})
db.people.insert({
"name": "Erin",
"places_id": original_id,
"url": "bc.example.net/Erin"
})
I am able to use a find on the places to get a certain name.
db.places.find({name : "Broadway Center"});
This will give the id. And then my application can use this ID to query the people to see who live here?
But, If i dont have a application. How would I go about doing this solely in a mongo shell? I was thinking about using find, and then iterating over the cursor using a forEach? But this seems a bit hacky.
Any suggestions?
You don't need to loop through using the cursor from find(), just use findOne() because a single document is returned with this method and you have access to the document directly (no need to apply cursor methods to the result). In mongo shell you can do this:
var result = db.places.findOne({name : "Broadway Center"});
if (result) {
var place_id = result._id;
var peopleArray = db.people.find({ "places_id": place_id }).toArray();
if (peopleArray.length > 0) { printjson (peopleArray[0]); }
}

Expand a date range in mongodb

I have a document structure like
{
"startDate": ISODate("2015-01-01T00:00:00Z"),
"endDate" : ISODate("2015-01-10T00:00:00Z"),
"foo" : "bar"
}
Is it possible to expand the date range like this?
{
"dates": [
ISODate("2015-01-01T00:00:00Z"),
ISODate("2015-01-02T00:00:00Z"),
ISODate("2015-01-03T00:00:00Z"),
ISODate("2015-01-04T00:00:00Z"),
ISODate("2015-01-05T00:00:00Z"),
ISODate("2015-01-06T00:00:00Z"),
ISODate("2015-01-07T00:00:00Z"),
ISODate("2015-01-08T00:00:00Z"),
ISODate("2015-01-09T00:00:00Z"),
ISODate("2015-01-10T00:00:00Z")
]
}
As far as I understood you want to add field dates for all your documents. Here is an approach I would use (you can do this in mongoshell):
1) iterate over all the documents modifying them
db.coll.find()..snapshot().forEach(function(o){
o.dates = func(o.startDate, o.endDate);
db.coll.save(o);
});
2) where you function func is something similar to this answer (you need to modify it a little bit because it looks like you need only dates without time included there.

Mongodb $elemMatch query inside map

I need to search inside a map element with a certain value in mongodb.
I have this element in data base:
{
"_id": ObjectId("52950e93c4aad399cff0d9f9"),
"_class": "com.company.model.customer.DbCustomer",
"version": NumberLong(0),
"channels": {
"adea3d4e-2a73-4f3e-8a89-a336d6132909": {
"value": "dominik.czech.aal#gmail.com",
"alias": "email1",
"deliveryChannel": "EMAIL",
"status": "GOOD",
"_class": "com.company.model.customer.CustomerEmail"
}
}
}
Where "adea3d4e-2a73-4f3e-8a89-a336d6132909" is a key of a map of channels.
What I want to search is a channel with certain value.
If "channels" were an array the query would be this way:
{ "channels" :
{ "$elemMatch" : { "value" : "dominik.czech.aal#gmail.com" } }
}
But, as channels is a map, I can't use this approach.
Is it possible to search inside a map the same way you search inside an array?
Notice that I want to use a single query, for security reasons I cannot use the map reduce functionality in my database.
Thanks in advance.
AFAIK it's not possible with the current MongoDB operators anyway, without scripting or map/reduce or knowing the keys you want to query in advance.
As a side note, you should think your data structure against how you want to query it - i.e. you should probably consider transform the channels document into an array.
i am not seeing any array set in above sample code, array set must be look like myarray[1,2,3]
so with this sample code if you want to search sub-field value you can try like following.
>db.Collection.find({"channels.value" : "dominik.czech.aal#gmail.com"})
Hope this will help.....