Filter Observables before subscribing angular2 - javascript

I have data like the one below in my mongoDB and I retrieve calling the service and later subscribing to it. But I want to filter the before subcribing to it in a way that i just subscribe to the filtered data base on my condition.
I want to filtered verifying that one of the camps in the data from the backend matches the "this.idcalbuscador". (See the .filter()). I haven't been able to achieve this, could anyone help? Just new to observables
Data
{
"_id" : ObjectId("588850b746f8ce140c1fe8cf"),
"idpertenalcalendario" : ObjectId("5885bfe452c6ba1d50f37f19"),
"enabled" : true,
"forma" : "Rombo",
"color" : "Red",
"type" : "point",
"descrip" : "ghghghgh",
"startDate" : "2017-01-15",
"nameHito" : "gjgjgjgg",
}
Code
//retrieve the datas
this._hitoService.getHitos()
.filter(resp => resp.idpertenalcalendario === this.idcalbuscador )
.subscribe(hito1 =>{
if (typeof this.nom_cal1 === "undefined"){
swal("Atencion!", "Busca un calendario con el buscador del Side Menu")
}else {
drawtimeline1_1(this.hito1, this.nom_cal1);
}
});

The filter function is not called for every item in your array, like it is for instance in Java's stream API. It is called for a single emittance of the Observable. That means the resp you work with in the filter function contains the array and not a single hito. That's why the following comparison will always return false:
resp.idpertenalcalendario === this.idcalbuscador
This is, at least, what I'd expect according to the names: getHitos returns an array of Hito. But Pierre Duc is right, it depends on your actual implementation.

Related

Retrieve data from Firebase using Google Apps Script

I'm developing a Google Spreadsheet to manage reservations for a hotel. It has two main tabs. One of them is used to make the reservations and the other one is used to make queries to the reservations already made. I managed to make it work just fine with the built-in tools of google apps script using a tab as database.
I'm trying to export my data to a Firebase database, but I cannot find how to fetch some information I need. My data is stored using a code generated using the date of the reservation as integer format + the name of the person without spaces. This is the JSON generated by firebase:
{
"44256001LarissaMeimbergBaraldi" : {
"code" : 44256001,
"date" : "2021-03-01T03:00:00.000Z",
"name" : "Larissa Meimberg Baraldi"
},
"44256001ÍcaroNovodeOliveira" : {
"code" : 44256001,
"date" : "2021-03-01T03:00:00.000Z",
"name" : "Ícaro Novo de Oliveira"
}
}
My question is: let's suppose I want to know all the reservations made for the day 01/March/2021, what is the code for me to look inside the objects and then, if they match my search, get the info I need?
I converted the JSON to an array of objects, then filtered by date. Added the console logs to check if everything is right. You can see the logs when you go to view -> executions in your script. Click on the function execution to see the logged objects.
function myFunction() {
var a ={
"44256001LarissaMeimbergBaraldi" : {
"code" : 44256001,
"date" : "2021-03-01T03:00:00.000Z",
"name" : "Larissa Meimberg Baraldi"
},
"44256001ÍcaroNovodeOliveira" : {
"code" : 44256001,
"date" : "2021-03-01T03:00:00.000Z",
"name" : "Ícaro Novo de Oliveira"
},
"44256002ÍcaroNovodeOliveira" : {
"code" : 44256002,
"date" : "2021-04-01T03:00:00.000Z",
"name" : "Ícaro Dovo de Oliveira"
}
};
var values_a = Object.values(a);
var keys_a = Object.keys(a);
var array_a = keys_a.map((item, index)=> {return {"key": item, "values": values_a[index]};});
console.log(array_a);
var filter_date = "2021-03-01T03:00:00.000Z";
var filtered_a=array_a.filter(item => {return item.values.date === filter_date;})
console.log(filtered_a);
}
Thank you for your help! But my point was actually a little bit different, maybe I wasn't so clear.
While trying to explain it to you, I found the answer to my question. It was right under my nose this whole time and I didn't notice it. Here is the solution I needed:
First, I have to assign a rule to my firebase telling it what element I will be working on, so if I want to find reservations based on the date, it would look like this:
{
"rules": {
".read": true,
".write": true,
".indexOn":["date"]
}
}
Then, back to my script, it will be like:
function getReservations() {
var ss = SpreadsheetApp.getActive().getSheetByName('Search');
var date = ss.getRange('C11').getValue();
var firebaseUrl = "https://script-examples.firebaseio.com/";
var base = FirebaseApp.getDatabaseByUrl(firebaseUrl);
var queryParameters = {orderBy:"date", equalTo: date};
var data = base.getData("", queryParameters);
for(var i in data) {
Logger.log(data[i].code, data[i].name, data[i].date);
}
}
The log retrieves:
[20-12-08 11:30:33:696 BRT] 44256001 Larissa Meimberg Baraldi 2021-03-01T03:00:00.000Z
[20-12-08 11:30:33:698 BRT] 44256001 Ícaro Novo de Oliveira 2021-03-01T03:00:00.000Z
This information was described on the documentation here:
https://sites.google.com/site/scriptsexamples/new-connectors-to-google-services/firebase/tutorials/read-and-write-data-in-firebase-from-apps-script
I think I got a little overwhelmed with the amount of information I got and skipped this part of the tutorial.
Thank you so much for your time and help.

Need to search API output in JSON format for value and print entire array content

I have googlesheets functions that parse json and import to sheets, you can find the code for the function in ImportJson file.
function IMPORTJSON(url,xpath){
try{
// /rates/EUR
var res = UrlFetchApp.fetch(url);
var content = res.getContentText();
var json = JSON.parse(content);
var patharray = xpath.split("/");
//Logger.log(patharray);
for(var i=0;i<patharray.length;i++){
json = json[patharray[i]];
}
//Logger.log(typeof(json));
if(typeof(json) === "undefined"){
return "Node Not Available";
} else if(typeof(json) === "object"){
var tempArr = [];
for(var obj in json){
tempArr.push([obj,json[obj]]);
}
return tempArr;
} else if(typeof(json) !== "object") {
return json;
}
}
catch(err){
return "Error getting data";
}
}
The functions is pretty simple and self explanatory . Disclosure I got this function from here. "https://www.youtube.com/watch?v=EXKhVQU37WM"
I had some additional requirements that this function cannot do. Need to search API output in JSON format for value and print entire array content.
For example I had a JSON output as below .
{
"symbol" : "AAPL",
"historicalDCF" : [ {
"date" : "2019-03-30",
"Stock Price" : 190.5064,
"DCF" : 199.51439324614452
}, {
"date" : "2018-12-29",
"Stock Price" : 156.4638,
"DCF" : 165.25974241335186
}, {
"date" : "2018-09-29",
"Stock Price" : 224.6375,
"DCF" : 233.0488839004929
}, {
"date" : "2018-06-30",
"Stock Price" : 184.3734,
"DCF" : 192.36145120758877
}, {
"date" : "2018-03-31",
"Stock Price" : 163.5502,
"DCF" : 172.0839412239145
}, {
"date" : "2017-12-30",
"Stock Price" : 168.339,
"DCF" : 178.05212237708827
}, {
"date" : "2017-09-30",
"Stock Price" : 149.7705,
"DCF" : 160.23613044781487
}, {
"date" : "2017-07-01",
"Stock Price" : 139.1847,
"DCF" : 150.3852802404117
}, {
"date" : "2017-04-01",
"Stock Price" : 138.8057,
"DCF" : 148.7456306248566
}, {
"date" : "2016-12-31",
"Stock Price" : 111.7097,
"DCF" : 120.02897160465633
}, {
"date" : "2016-09-24",
"Stock Price" : 108.0101,
"DCF" : 116.70616209306208
}
]
}
You can also check live version of this API on this link " https://financialmodelingprep.com/api/v3/company/historical-discounted-cash-flow/AAPL?period=quarter"
To get DCF value on "2019-03-30", I can simply use functions as this:
=IMPORTJSON("https://financialmodelingprep.com/api/v3/company/historical-discounted-cash-flow/AAPL?period=quarter","historicalDCF/0/DCF")
What if I need to search through date and get the value of Stock Price? For example I need to get the value of Stock price and DCF on this date "2017-09-30" . How could I do it without knowing array position ?
So for this I need help either by creating new function or modifying existing function to get this functionality.
Help is highly appreciated and thanks in advance to all the gurus out there.
json.historicalDCF.filter((el) => el.date === "2017-07-01") will return the object that matches that date.
You could get the return like:
function findByDate(dateParam) {
return json.historicalDCF.filter((el) => el.date === dateParam)
}
var theInfoIWantVariable = findByDate("2017-1-1-make-sure-this-is-a-string")
Given that your IMPORT function is returning a JSON object (and assuming the format is what you've shown in your post), then you could simply use a regular javascript filter() function to get the specific date you want:
const data =IMPORTJSON("https://financialmodelingprep.com/api/v3/company/historical-discounted-cash-flow/AAPL?period=quarter","historicalDCF");
// now, data is the JSON array containing the historical data. All the data. We can filter it for whatever we want.
const myOneDayRecord = data.find( record => record.date === '2016-03-30' );
// so the variable myOneDayRecord is the specific record by date we wanted. Now we can use it as a normal javascript object.
console.log(`So on ${myOneDayRecord.date}, the stock price was ${myOneDayRecord["Stock Price"] } and the DCF was ${myOneDayRecord.DCF}`);
// note that, in the above line,I had to use bracket notation to get to the 'Stock Price' property. That's because of the space in the property name.
If I understood you correctly, you want to create a custom function that will:
Accept a url, a xpath and a date as a parameter.
Call IMPORTJSON and pass the previous url and xpath as parameters.
In the JSON returned by IMPORTJSON, find the item in historicalDCF whose date matches the one passed as a parameter.
Return its corresponding Stock Price.
If all of the abose is correct, then you could do something along the following lines:
function GETSTOCKPRICE(url, xpath, date) {
var jsonData = IMPORTJSON(url,xpath);
var historical = jsonData["historicalDCF"];
var stockPrice;
for (var i = 0; i < historical.length; i++) {
if (historical[i]["date"] === date) {
stockPrice = historical[i]["Stock Price"];
break;
}
}
return stockPrice;
}
And then, you can use this function in your sheet by passing it the correct parameters. For example, if you want to get the stock price corresponding to 2017-09-30:
=GETSTOCKPRICE("https://financialmodelingprep.com/api/v3/company/historical-discounted-cash-flow/AAPL?period=quarter", "historicalDCF/0/DCF", "2017-09-30")
Notes:
Methods like filter or find, arrow functions and declarations like const won't work here, since Apps Script doesn't currently support ES6.
You could also modify GETSTOCKPRICE so that it only accepts date as a parameter, and the call to IMPORTJSON has its parameters hard-coded (this would make sense if you're always going to use IMPORTJSON for this exact url and xpath). But that's up to you.
I hope this is of any help.

How can I reformat this simple JSON so it doesn't catch "Circular structure to JSON" exception?

Introduction
I'm learning JavaScript on my own and JSON its something along the path. I'm working on a JavaScript WebScraper and I want, for now, load my results in JSON format.
I know I can use data base, server-client stuff, etc to work with data. But I want to take this approach as learning JSON and how to parse/create/format it's my main goal for today.
Explaining variables
As you may have guessed the data stored in the fore mentioned variables comes from an html file. So an example of the content in:
users[] -> "Egypt"
GDP[] -> "<td> $2,971</td>"
Regions[] -> "<td> Egypt </td>"
Align[] -> "<td> Eastern Bloc </td>"
Code
let countries = [];
for(let i = 0; i < users.length; i++)
{
countries.push( {
'country' : [{
'name' : users[i],
'GDP' : GDP[i],
'Region' : regions[i],
'Align' : align[i]
}]})
};
let obj_data = JSON.stringify(countries, null, 2);
fs.writeFileSync('countryballs.json', obj_data);
Code explanation
I have previously loaded into arrays (users, GDP, regionsm align) those store the data (String format) I had extracted from a website.
My idea was to then "dump" it into an object with which the stringify() function format would format it into JSON.
I have tested it without the loop (static data just for testing) and it works.
Type of error
let obj_data = JSON.stringify(countries, null, 2);
^
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Node'
| property 'children' -> object with constructor 'Array'
| index 0 -> object with constructor 'Node'
--- property 'parent' closes the circle
What I want from this question
I want to know what makes this JSON format "Circular" and how to make this code work for my goals.
Notes
I am working with Node.js and Visual Studio Code
EDIT
This is further explanation for those who were interested and thought it was not a good question.
Test code that works
let countries;
console.log(users.length)
for(let i = 0; i < users.length; i++)
{
countries = {
country : [
{
"name" : 'CountryTest'
}
]
}
};
let obj_data = JSON.stringify(countries, null, 2);
fs.writeFileSync('countryballs.json', obj_data);
});
Notice in comparison to the previous code, right now I am inputing "manually" the name of the country object.
This way absolutely works as you can see below:
Now, if I change 'CountryTest' to into a users[i] where I store country names (Forget about why countries are tagged users, it is out of the scope of this question)
It shows me the previous circular error.
A "Partial Solution" for this was to add +"" which, as I said, partially solved the problem as now there is not "Circular Error"
Example:
for(let i = 0; i < users.length; i++)
{
countries = {
country : [
{
"name" : users[i]+''
}
]
}
};
Resulting in:
Another bug, which I do not know why is that only shows 1 country when there are 32 in the array users[]
This makes me think that the answers provided are not correct so far.
Desired JSON format
{
"countries": {
"country": [
{
"name": "",
"GDP" : "",
"Region" : "",
"Align" : ""
},
{
"name": "",
"GDP" : "",
"Region" : "",
"Align" : ""
},
{
"name": "",
"GDP" : "",
"Region" : "",
"Align" : ""
}
]}
}
Circular structure error occurs when you have a property of the object which is the object itself directly (a -> a) or indirectly (a -> b -> a).
To avoid the error message, tell JSON.stringify what to do when it encounters a circular reference. For example, if you have a person pointing to another person ("parent"), which may (or may not) point to the original person, do the following:
JSON.stringify( that.person, function( key, value) {
if( key == 'parent') { return value.id;}
else {return value;}
})
The second parameter to stringify is a filter function. Here it simply converts the referred object to its ID, but you are free to do whatever you like to break the circular reference.
You can test the above code with the following:
function Person( params) {
this.id = params['id'];
this.name = params['name'];
this.father = null;
this.fingers = [];
// etc.
}
var me = new Person({ id: 1, name: 'Luke'});
var him = new Person( { id:2, name: 'Darth Vader'});
me.father = him;
JSON.stringify(me); // so far so good
him.father = me; // time travel assumed :-)
JSON.stringify(me); // "TypeError: Converting circular structure to JSON"
// But this should do the job:
JSON.stringify(me, function( key, value) {
if(key == 'father') {
return value.id;
} else {
return value;
};
})
The answer is from StackOverflow question,
Stringify (convert to JSON) a JavaScript object with circular reference
From your output, it looks as though users is a list of DOM nodes. Rather than referring to these directly (where there are all sort of possible cyclical structures), if you just want their text, instead of using users directly, try something like
country : [
{
"name" : users[i].textContent // maybe also followed by `.trim()
}
]
Or you could do this up front to your whole list:
const usersText = [...users].map(node => node.textContent)
and then use usersText in place of users as you build your object.
If GDP, regions and align are also references to your HTML, then you might have to do the same with them.
EUREKA!
As some of you have mentioned above, let me tell you it is not a problem of circularity, at first..., in the JSON design. It is an error of the data itself.
When I scraped the data it came in html format i.e <td>whatever</td>, I did not care about that as I could simply take it away later. I was way too focused in having the JSON well formatted and learning.
As #VLAZ and #Scott Sauyezt mentioned above, it could be that some of the data, if it is not well formatted into string, it might be referring to itself somehow as so I started to work on that.
Lets have a look at this assumption...
To extract the data I used the cheerio.js which gives you a kind of jquery thing to parse html.
To extract the name of the country I used:
nullTest = ($('table').eq(2).find('tr').eq(i).find('td').find('a').last());
//"Partial solution" for the OutOfIndex nulls
if (nullTest != null)
{
users.push(nullTest);
}
(nullTest helps me avoid nulls, I will implement some RegEx when everything works to polish the code a bit)
This "query" would output me something like:
whatEverIsInHereIfThereIsAny
or else.
to get rid off this html thing just add .html() at the end of the "jquery" such as:
($('table').eq(2).find('tr').eq(i).find('td').find('a').last().html());
That way you are now working with String and avoiding any error and thus solves this question.

How do I to target a single value in firebase database?

I'm having trouble figuring out how to target a single object in the firebase database. For example, I want to have a specific word/definition shown when I click an index card. I'm using this to store the data:
wordVal = $("#word").val();
defVal = $("#def").val();
data = firebase.database().ref("indexCards");
data.push( { 'word': wordVal, 'definition': defVal } );
and this to retrieve it:
data.on("child_added", function(snapshot){
console.log(snapshot.val().word);
console.log(snapshot.val().definition);
});
This gives me the whole list of words and definitions. I want to refer to specific words and specific definitions, separately. The docs say that I can reference the specific values by doing this - firebase.database().ref("child/path").
But my question is...how can I reference the path when the parents are those random numbers and letters (see below)? I know that these are unique IDs generated by firebase, but I don't know how to access them like I'd access ordinary objects.
{
"-KQIOHLNsruyrrnAhqis" : {
"definition" : "person, place, thing",
"word" : "noun"
},
"-KQIOO7Wtp2d5v2VorqL" : {
"definition" : "device for photos",
"word" : "camera"
},
"-KQISp4WMnjABxQayToD" : {
"definition" : "circus act",
"word" : "clown"
},
"-KQITC9W1lapBkMyiL7n" : {
"definition" : "device used for cutting",
"word" : "scissors"
}
}
You can use a query like this:
data = firebase.database().ref('indexCards').orderByChild('word').equalTo('noun')
It is self-explanatory, we get reference to indexCards where value of key word is equal noun, so it will return object with key -KQHZ3xCHTQjuTvonSwj
Link to Firebase docs: Retrieve data - Sorting and Filtering data
You need to put the initial push into an object then call the object later. ie
To PUSH data:
firebase.database().ref().push( { 'word': wordVal, 'definition': defVal } )
To UPDATE data or call it later:
firebase.database().ref("indexCards").set({})
or in this case:
data.set({})

Couchdb reverses start and end key when descending is true

I have a CouchDB that contains items with something called save_data (actual data I need), rel (as related account - account linked to that document) and created_at (date of creation).
When I first created my view which I called recent-items I thought that items in that view are sorted in order they were created in, but it didn't take long for me to discover just how wrong I was. I wanted to get all documents related to one user (rel, save_profile in my js which calls the db.view funcion) and then sort them based on created_at so I created map funcion:
function(doc) {
if (doc.rel) {
var p = doc.save_data || {};
var r = doc.rel || {};
var q = doc.created_at || {};
emit([doc.rel], {save_data: doc.save_data, rel: doc.rel});
}
};
and then I called it with these parameters:
db.view(design + "/recent-items", {
descending : "true",
limit : 10,
update_seq : true,
key : [save_profile],
success : function(data) {
...somecode...
}
});
and then I noticed that they didn't appear in the order I wanted, but sorted by their ID which makes sense now, but that's not what I needed. So I did this: I reworked map function so that it shows user and date in key (as fields to be sorted by)
function(doc) {
if (doc.rel) {
var p = doc.save_data || {};
var r = doc.rel || {};
var q = doc.created_at || {};
emit([doc.rel, doc.created_at], {save_data: doc.save_data, rel: doc.rel});
}
};
and then I used startkey instead of key in db.view like this:
db.view(design + "/recent-items", {
descending : "true",
limit : 10,
update_seq : true,
startkey : [save_profile, null],
success : function(data) {
...somecode...
}
});
so that I get all documents related to save_profile but sorted by date also. I did get them, but I also got documents from other users with it so that function is completely unreliable. What I did then is implement endkey also, like this:
db.view(design + "/recent-items", {
descending : "true",
limit : 10,
update_seq : true,
startkey : [save_profile, null],
endkey : [save_profile, {}],
success : function(data) {
...somecode...
}
});
but then I get empty view as result.
Dates I use are in this format:
"2013-05-13T11:59:22.281Z"
and profiles are something like this:
{"rand":"0.26928815129213035","nickname":"Nickname","email":"Label for Gravatar","url":"URL","gravatar_url":"http://www.gravatar.com/avatar/35838c85593335493a1fa916863fee0c.jpg?s=40&d=identicon","name":"testacc"}
I also tried replacing [] and {} in start/endkeys with "0000-00-00T00:00:00.000Z" and "9999-99-99T99:99:99.999Z", but it changed nothing. So... Any ideas? As far as I've seen in other similar problems people just used {} as end key and left startkey without second parameter but that doesn't work here either.
Edit: Solved!
Alright folks, believe it or not I've done it in this way:
I changed my map function to display created at and profile in this way:
function(doc) {
if (doc.rel) {
var p = doc.save_data || {};
var r = doc.rel || {};
var q = doc.created_at || {};
emit([doc.rel, doc.created_at], {save_data: doc.save_data, rel: doc.rel});
}
};
and it appears that if you set descending to true before setting start and end keys you have to reverse the search interval so that endkey contains starting value and startkey containst ending value, like this:
db.view(design + "/recent-items", {
descending : "true",
update_seq : "true",
startkey : [save_profile.name, save_profile.rand, {}],
endkey : [save_profile.name, save_profile.rand, null],
inclusive_end : "true",
success : function(data) {
...somecode...
}
});
That did the trick and it works flawlessly (but also with a complete absence of logic).
I should have caught this before. So when you do the following, it works the way you'd like:
db.view('_design/test_views/_view/view1', startkey: ["account2"])
=> {"total_rows"db.view('_design/test_views/_view/view1')
=> {"total_rows"=>4, "offset"=>0, "rows"=>[{"id"=>"test1", "key"=>["account1", "2009-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account1"}}, {"id"=>"test2", "key"=>["account2", "2012-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account2"}}, {"id"=>"test3", "key"=>["account3", "2011-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account3"}}, {"id"=>"test4", "key"=>["account4", "2010-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account4"}}]}`
db.view('_design/test_views/_view/view1',startkey: ["account2"])
=> {"total_rows"=>4, "offset"=>1, "rows"=>[{"id"=>"test2", "key"=>["account2", "2012-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account2"}}, {"id"=>"test3", "key"=>["account3", "2011-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account3"}}, {"id"=>"test4", "key"=>["account4", "2010-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account4"}}]}`
db.view('_design/test_views/_view/view1',
startkey: ["account2"],
endkey: ["account3",{}])
=> {"total_rows"=>4, "offset"=>1, "rows"=>[{"id"=>"test2", "key"=>["account2", "2012-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account2"}}, {"id"=>"test3", "key"=>["account3", "2011-05-13T11:59:22.281Z"], "value"=>{"rel"=>"account3"}}]}`.
But when you set descending=true, you reverse the order first. Previously you were setting your start and end keys the way that you should when descending=false, but you need to reverse them when you change descending. The CouchDB Definitive Guide is great and talks about these reversed results, worth the read.
I totally missed that you were setting descending, sorry for the confusion.
I think the startkey [save_profile, null] is what is messing you up (although it works via curl). Whatever library you're using (db.view is some javascript lib or ruby CouchRest maybe?) may be recoding null as something else. You can always verify this compared to curl by breaking out the packet sniffer (i.e. Wireshark), although you'll get an idea how inefficient a library can be with all the extra requests it makes. Can make the troubleshooting more difficult.
What results do you get with curl? I mocked up your database, and here's what I get:
$ curl -X GET 'http://localhost:5984/test2/_design/test_views/_view/view1'
{"total_rows":4,"offset":0,"rows":[
{"id":"test1","key":["account1","2009-05-13T11:59:22.281Z"],"value":{"rel":"account1"}},
{"id":"test2","key":["account2","2012-05-13T11:59:22.281Z"],"value":{"rel":"account2"}},
{"id":"test3","key":["account3","2011-05-13T11:59:22.281Z"],"value":{"rel":"account3"}},
{"id":"test4","key":["account4","2010-05-13T11:59:22.281Z"],"value":{"rel":"account4"}}
]}
$ curl -X GET 'http://localhost:5984/test2/_design/test_views/_view/view1?startkey=\["account2"\]&endkey=\["account3",\{\}\]'
{"total_rows":4,"offset":1,"rows":[
{"id":"test2","key":["account2","2012-05-13T11:59:22.281Z"],"value":{"rel":"account2"}},
{"id":"test3","key":["account3","2011-05-13T11:59:22.281Z"],"value":{"rel":"account3"}}
]}
Notice that I am not using null, I'm just leaving that element of the key out. Also notice in curl (and possibly you're library), you have to be really careful what you put in start/end keys. I have to escape all bash stuff that even single quotes don't escape (i.e. [ { etc), and curl escapes spaces as %20, which is then used for the keys. A good approach is to run couchdb not forked out, or just watch its logs, and see what the incoming requests look like. Has been a source of issues for me.
You're using the wildcards in the keys, which is a cool feature. You may have seen this, I've re-read this snippet a few times to try to understand them.
I've beat my head on this similar problem too, until I really understood what views do. But what you're doing should be possible. Any more complicated searches, and I'd really consider Elasticsearch or something similar. The river install for it is really easy, and the queries are pretty similar. But you don't have to work around the limitations of views and orders.
Hope that helps.
Alright folks, believe it or not I've done it in this way:
I changed my map function to display created at and profile in this way:
function(doc) {
if (doc.rel) {
var p = doc.save_data || {};
var r = doc.rel || {};
var q = doc.created_at || {};
emit([doc.rel, doc.created_at], {save_data: doc.save_data, rel: doc.rel});
}
};
and it appears that if you set descending to true before setting start and end keys you have to reverse the search interval so that endkey contains starting value and startkey containst ending value, like this:
db.view(design + "/recent-items", {
descending : "true",
update_seq : "true",
startkey : [save_profile.name, save_profile.rand, {}],
endkey : [save_profile.name, save_profile.rand, null],
inclusive_end : "true",
success : function(data) {
...somecode...
}
});
That did the trick and it works flawlessly (but also with a complete absence of logic).

Categories

Resources