I've recently added the Sphider crawler to my site in order to add search functionality. But the default search.php that comes with the distribution of Sphider that I downloaded is too plain and doesn't integrate well with the rest of my site. I have a little navigation bar at the top of the site which has a search box in it, and I'd like to be able to access Sphider's search results through that search field using Ajax. To do this, I figure I need to get Sphider to return its results in JSON format.
The way I did that is I used a "theme" that outputs JSON (Sphider supposts "theming" its output). I found that theme on this thread on Sphider's site. It seems to work, but more strict JSON parsers will not parse it. Here's some example JSON output:
{"result_report":"Displaying results 1 - 1 of 1 match (0 seconds) ", "results":[ { "idented":"false", "num":"1", "weight":"[100.00%]", "link":"http://www.avtainsys.com/articles/Triple_Contraints", "title":"Triple Contraints", "description":" on 01/06/12 Project triple constraints are time, cost, and quality. These are the three constraints that control the performance of the project. Think about this triple-constraint as a three-leg tripod. If one of the legs is elongated or", "link2":"http://www.avtainsys.com/articles/Triple_Contraints", "size":"3.3kb" }, { "num":"-1" } ], "other_pages":[ { "title":"1", "link":"search.php?query=constraints&start=1&search=1&results=10&type=and&domain=", "active":"true" }, ] }
The issue is that there is a trailing comma near the end. According to this, "trailing commas are not allowed" when using PHP's json_decode() function. This JSON also failed to parse using this online formatter. But when I took the comma out, it worked and I got this better-formatted JSON:
{
"result_report":"Displaying results 1 - 1 of 1 match (0 seconds) ",
"results":[
{
"idented":"false",
"num":"1",
"weight":"[100.00%]",
"link":"http://www.avtainsys.com/articles/Triple_Contraints",
"title":"Triple Contraints",
"description":" on 01/06/12 Project triple constraints are time, cost, and quality. These are the three constraints that control the performance of the project. Think about this triple-constraint as a three-leg tripod. If one of the legs is elongated or",
"link2":"http://www.avtainsys.com/articles/Triple_Contraints",
"size":"3.3kb"
},
{
"num":"-1"
}
],
"other_pages":[
{
"title":"1",
"link":"search.php?query=constraints&start=1&search=1&results=10&type=and&domain=",
"active":"true"
}
]
}
Now, how would I do this programmatically? And (perhaps more importantly), is there a more elegant way of accomplishing this? And you should know that PHP is the only language I can run on my shared hosting account, so a Java solution for example would not work for me.
In search_result.html, you can surround the , at the end of the foreach loop with condition to only print if the index is strictly less than the number of pages - 1.
Related
I am new to Ruby and have been stuck at this for a while now. I am getting a JSON responses as mentioned below and aim to search for the substring where the value of its substring is something as specified by me.
For example, I am getting the response below:
{
"00:00:00:CC:00:CC": {
"family": "lladdr"
},
"10.0.0.20": {
"family": "inet",
"prefixlen": "24",
"netmask": "255.255.255.0",
"broadcast": "10.0.0.255",
"scope": "Global"
},
"ff00::f00:00ff:fff0:00f0": {
"family": "inet6",
"prefixlen": "64",
"scope": "Link",
"tags": []
}
}
I need to get the value of the parent where the key family has a value equal to inet. In this case, I just want 10.0.0.20 as output when family equals inet.
I went through multiple questions here, and Google did not help. I understand that I will need to parse the JSON using JSON.parse, and then use maybe find or select to get my answer, but I was not able to get it working.
I am not sure if there is any other way I can do this like you would do in Bash using grep or awk. One hack might be to use something like foo.[46..54] which will output the IP, but again I believe that would be a bad way of solving this.
Use Hash#invert
Assuming that your Hash is already stored in response using JSON#parse, one way to solve the problem is to invert the Hash with the Hash#invert method. For example:
# Return an Array of IPv4, then pop the last/only String value.
response.invert.select { |h| h.values.include? 'inet' }.values.pop
#=> "10.0.0.20"
This is quick and simple, and it works with your provided data. However, there are some minor caveats.
Caveats
Assumes there is only one IPv4 address in the response Hash. If you have more than one key with inet as a value, don't use pop and deal with the resulting Array as you see fit. For example:
response.invert.select { |h| h.values.include? 'inet' }.values
#=> ["10.0.0.20"]
It assumes the key for each top-level JSON object is an IP address. We're not really validating anything.
It works for the JSON you have, but isn't solving for arbitrarily nested or varied data structures. If you have different kinds of inputs, consider it "some assembly required."
If you have no inet family, then {}.values.pop may return nil. Make sure you plan for that in your application.
None of these are show-stoppers for your particular use case, but they are certainly worth keeping in mind. Your mileage may vary.
If you want the family inet,
result = JSON.parse(response)
family = result.detect { |k,v| v['family'] == 'inet' }
family[0] # 10.0.0.20
Note that detect will return an array.
I have a rather big Json object that I am receiving via $http that I want to share between 2 controllers. To give you an idea - both controllers share the parent most array (marked as levels), and then within the levels there are key:values with nested arrays ( 2 of them) and each controller uses and edits them separately. I am trying to consolidate this as much as possible so I thought if i could control 1 json between 2 controllers this would work.
I want to be able to edits each sub array and push back to the server as a whole, but before I attempt this step I would like to be sure something like this is even possible. I have tried using a factory and service to no avail. I am slo curious if I can do this and I bring in the array - is it 2 way binded? The first controller should be able to add more levels, and the second one can add to them in a differen't way the first one can't. If I were to bring in the json and share it between controllers and added a level on the first one, would it show on the second?
I have been banging my head against this for a while now, so any insight or direction would be very appreciated. Thanks!!
I took a stab at what the json might look like (forgive me if the syntax is off)-
{
"level1": {
"form": {
"form1": "sample1",
"form2": "sample2",
"form3": 500,
"form4": 500
}
"sublevels": {
"subL": ["1", "2", "3"],
"help1": "main_window",
"help2": 500
}},
"level2": {
"form": {
"form1": "sample1",
"form2": "sample2",
"form3": 500,
"form4": 500
}
"sublevels": {
"subL": ["1", "2", "3"],
"help1": "main_window",
"help2": 500
}
}
}
so both controllers would build off the levels, something like "level in levels" ng-repeat type scenario, but controller 1 would use the "Form" key, and controller 2 would use the "subevels" keys. they would be able to edit those sections and post the whole sting back to the server for a save. I don't have much else because the factories/services I Tried to setup didn't seem to work at all. Thanks!
you can put it on service, but a simpler way is use rootscope, or create a parent controller common for both of your controllers
Hi so I'm new to CouchDB looks great so far, but really struggling with what must be simple to do!
I have documents structured as:
{
"_id" : "245431e914ce42e6b2fc6e09cb00184d",
"_rev": "3-2a69f0325962b93c149204aa3b1fa683",
"type": "student",
"studentID": "12345678",
"Name": "Test",
"group: "A"
}
And would like to access them them with queries such as http://couchIP/student?group=A or something like that. Are Views what I need here? I don't understand how to take the parameter from the query in the Map functions in Views. example:
function(doc,req) {
if(req.group==='A'){
emit(doc.id, doc.name);
}
}
Is my understanding of how Couch is working wrong or what's my problem here? Thanks in advance, I'm sure this is Couch 101
Already read through http://guide.couchdb.org/ but it didn't really answer the question!
You need views to achieve the desired results.
Define the following map function inside a view of a design document. ( let's name the view "byGroup" and assume this lives in a design document named "_design/students" )
function(doc) {
if(doc.group){
emit(doc.group,null);
}
}
Results can be obtained from the following url
http://couchIP:5984/dbname/_design/students/_view/byGroup?startkey="A"&endkey="A"&include_docs=true
To have friendly url couchdb also provides url rewriting options.
You need to some further reading about views and the relevance that they return key/pair values.
It's not clear what you want to return from the view so I'll guess. If you want to return the whole document you'd create a view like:
function (doc) { emit(doc.group, doc) };
This will emit the group name as a key which you can lookup against, the whole doc will be returned as the value when you look it up.
If you want to just have access to the names of those users you want to do something like:
function (doc) { emit(doc.group, doc.name) };
Your question arises from a misconception about what a view does. Views use map/reduce to generate a representation of your data. You have no control of the output of your view in your query because the view is updated according to changes in your DB documents only.
Using a list is also not a good option. It may seem that you can use knowledge of your request in your list to generate a different output depending on the query parameters but this is wrong because couchdb uses ETags for caching and this means that most times you will get the same answer regardless of your list parameters since the underlying documents won't have changed. There is a trick though to fool couchdb in this case and this implies using two different alternating users but I wouldn't even try this way because surely there are easier ways to achieve your objectives and you can probably solve your problem using group as a key in your map function.
Which is the better data format for a JSON. The requirement is to be able to store and retrieve information about how many projects are deployed on to a server.
Object-Based Design
{
"Server1":{
"project1":{
"buildNo":"290",
"deployed":"12/12/2012"
},
"project2":{
"buildNo":"291",
"deployed":"11/12/2012"
},
"project3":{
"buildNo":"209",
"deployed":"11/12/2012"
}
}
}
Array-Based Design
{
"Server1":[
{"project1":{
"buildNo":"290",
"deployed":"12/12/2012"
}},
{"project2":{
"buildNo":"291",
"deployed":"11/12/2012"
}},
{"project3":{
"buildNo":"209",
"deployed":"11/12/2012"
}}
]
}
Please do let me know your thoughts for or against either of these approaches.
Is the order of projects significant?
If it is, then an array is the simplest way to represent that.
If it is not, then array requires an unnecessary preprocessing step to map array indexes to project names before you can access them by name.
My thoughts:
Parsing:
Both are of similar complexity.
Adding/Deleting:
Both are of similar complexity
Readability/Representation of Information:
The first indicates a fixed structure whereas the second suggests that projects may be added removed later.
Im using Vaadin as the framework to represent a presentation layer for my application.
I have a trouble with the Vaadin Table listing. I load 1000 rows with 5 columms (yes I need to load all 1000, there is also an option to load less. =)) but this is not very fast when using Vaadin. When I look at the Json sent I realize that there are lots of variables that i dont whant to be sent for everu table row.
This is the response i have as of now:
"domaindom-000000938.co_uk",
["17",
{"id": "PID783","readonly":true,"locale": "en_EN","format": "yyyy-MM-dd","strict":true,"wn":false,"parsable":true,
"v":{"day":7,"month":2,"year":2011}}],
["17",
{"id": "PID784","readonly":true,"locale": "en_EN","format": "yyyy-MM-dd","strict":true,"wn":false,"parsable":true,
"v":{"day":7,"month":2,"year":2011}}],
["17",
{"id": "PID785","readonly":true,"locale": "en_EN","format": "yyyy-MM-dd","strict":true,"wn":false,"parsable":true,
"v":{"day":7,"month":2,"year":2012}}],
"","","ENG"],
["tr",{"key":206},"
I would like to transform this Json to be more like
"domaindom-000000938.co_uk",
["17",
{"id": "PID783","locale": "en_EN",,"strict":true,"wn":false,"v1":"2011-07-02", "v2":"2011-02-07", "v3":"2012-02-07"}],
As you can see I have removed a couple of variables and inserted the date varialble in the same clauses.
So my quiestion is this. In Vaadin, how do I modify the way Vaadin creates the Json response? I currently use the BeanItemContainer to hold my objects like this:
public BeanItemContainer getPagedDataSource(){
List<Object> mylist = DAO.getDAO().createQuery(query, index, max);
return new BeanItemContainer<Object>(type, mylist);
}
Thanks for any help or feedback!
/Marthin
First, that JSON is part of Vaadin's internal communication and you should not modify it. However, if you wish to check it out, it is the JsonPaintTarget along with the paintContent-method of the component in question (the Table) that creates the JSON.
Vaadin today operates in an unprecedented way. Everything will change in the application must be sent to the client. On the client side, each component is treated separately and therefore the response must address all components changed.
Each row in the table is a separate component because the answer is so long.
My proposed solution:
write your own implementation of the table - hard
the imposition of restrictions - easy, but it's prosthesis