I'm new to angularJS. I have a requirement to perform a search on JSON data. Here is an example JSON structure
countries = [
{
"country_name" : "India",
"stations" : [
{
"name": "Dream Factory"
}
]
},
{
"country_name" : "Indonesia",
"stations" : [
{
"name": "Drummer Factory"
},
{
"name": "Beats"
}
]
}
]
Say I type Ind, I need the countries matching the string and return both India and Indonesia
also In other field, typing Factory should retrieve station names which matches the string (here Drummer Factory, Dream Factory).
What is the simple way to achieve this?
Is there any built-in directive which solves this or can I use filters, If yes, please post with example...
You can use the filter named 'filter' (yes it's a little confusing): http://docs.angularjs.org/api/ng.filter:filter
Here's a demo: http://jsfiddle.net/g/pXnRs/4/
HTML:
<div ng-controller="CountryController">
Filter: <input ng-model="nameFilter" />
<ul>
<li ng-repeat="country in countries | filter: nameFilter">
{{country | json}}
</li>
</ul>
</div>
JS:
var app = angular.module('app', []);
app.controller('CountryController', function($scope){
$scope.nameFilter = '';
$scope.countries = [
{
"country_name" : "India",
"stations" : [
{
"name": "Dream Factory"
}
]
},
{
"country_name" : "Indonesia",
"stations" : [
{
"name": "Drummer Factory"
},
{
"name": "Beats"
}
]
}];
});
angular.bootstrap(document, ['app']);
If you need stations only as results, you should first flatten the JSON object hierarchy into a list of stations.
Related
I have a list example_list contains two dict objects, it looks like this:
[
{
"Meta": {
"ID": "1234567",
"XXX": "XXX"
},
"bbb": {
"ccc": {
"ddd": {
"eee": {
"fff": {
"xxxxxx": "xxxxx"
},
"www": [
{
"categories": {
"ppp": [
{
"content": {
"name": "apple",
"price": "0.111"
},
"xxx: "xxx"
}
]
},
"date": "A2020-01-01"
}
]
}
}
}
}
},
{
"Meta": {
"ID": "78945612",
"XXX": "XXX"
},
"bbb": {
"ccc": {
"ddd": {
"eee": {
"fff": {
"xxxxxx": "xxxxx"
},
"www": [
{
"categories": {
"ppp": [
{
"content": {
"name": "banana",
"price": "12.599"
},
"xxx: "xxx"
}
]
},
"date": "A2020-01-01"
}
]
}
}
}
}
}
]
now I want to filter the items and only keep "ID": "xxx" and the correspoding value for "price": "0.111", expected result can be something similar to :
[{"ID": "1234567", "price": "0.111"}, {"ID": "78945612", "price": "12.599"}]
or something like {"1234567":"0.111", "78945612":"12.599" }
Here's what I've tried:
map_list=[]
map_dict={}
for item in example_list:
#get 'ID' for each item in 'meta'
map_dict['ID'] = item['meta']['ID']
# get 'price'
data_list = item['bbb']['ccc']['ddd']['www']
for data in data_list:
for dataitem in data['categories']['ppp']
map_dict['price'] = item["content"]["price"]
map_list.append(map_dict)
print(map_list)
The result for this doesn't look right, feels like the item isn't iterating properly, it gives me result:
[{"ID": "78945612", "price": "12.599"}, {"ID": "78945612", "price": "12.599"}]
It gave me duplicated result for the second ID but where is the first ID?
Can someone take a look for me please, thanks.
Update:
From some comments from another question, I understand the reason for the output keeps been overwritten is because the key name in the dict is always the same, but I'm not sure how to fix this because the key and value needs to be extracted from different level of for loops, any help would be appreciated, thanks.
as #Scott Hunter has mentioned, you need to create a new map_dict everytime you are trying to do this. Here is a quick fix to your solution (I am sadly not able to test it right now, but it seems right to me).
map_list=[]
for item in example_list:
# get 'price'
data_list = item['bbb']['ccc']['ddd']['www']
for data in data_list:
for dataitem in data['categories']['ppp']:
map_dict={}
map_dict['ID'] = item['meta']['ID']
map_dict['price'] = item["content"]["price"]
map_list.append(map_dict)
print(map_list)
But what are you doing here is that you are basically just "forcing" your way through ... I recommend you to take a break and check out somekind of tutorial, which will help you to understand how it really works in the back-end. This is how I would have written it:
list_dicts = []
for example in example_list:
for www in item['bbb']['ccc']['ddd']['www']:
for www_item in www:
list_dicts.append({
'ID': item['meta']['ID'],
'price': www_item["content"]["price"]
})
Good luck with this problem and hope it helps :)
You need to create a new dictionary for map_dict for each ID.
In my logic app, I have a JSON object (parsed from an API response) and it contains an object array.
How can I find a specific element based on attribute values... Example below where I want to find the (first) active one
{
"MyList" : [
{
"Descrip" : "This is the first item",
"IsActive" : "N"
},
{
"Descrip" : "This is the second item",
"IsActive" : "N"
},
{
"Descrip" : "This is the third item",
"IsActive" : "Y"
}
]
}
Well... The answer is in plain sight ... There's a FILTER ARRAY action, which works on a JSON Object (from PARSE JSON action).. couple this with an #first() expression will give the desired outcome.
You can use the Parse JSON Task to parse your JSON and a Condition to filter for the IsActive attribute:
Use the following Schema to parse the JSON:
{
"type": "object",
"properties": {
"MyList": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Descrip": {
"type": "string"
},
"IsActive": {
"type": "string"
}
},
"required": [
"Descrip",
"IsActive"
]
}
}
}
}
Here how it looks like (I included the sample data you provided to test it):
Then you can add the Condition:
And perform whatever action you want within the If true section.
I have trouble in update the fields in solr-4.10
Assume that I have the doc below:
"docs": [
{
"id": "2001354750",
"post": [
"小马也疯狂------地位之争。"
],
"_version_": 1560655968803487700
},
{
"id": "2001187260",
"post": [
"北京的小纯洁们,周日见。#硬汉摆拍清纯照#"
],
"_version_": 1560655968822362000
}
]
but I want to add field cmnt into doc like below:
"docs": [
{
"id": "2001354750",
"post":"小马也疯狂------地位之争。",
"cmnt":"Really?",
"_version_": 1560655968803487700
},
{
"id": "2001187260",
"post": "北京的小纯洁们,周日见。#硬汉摆拍清纯照#",
"cmnt":"Shy",
"_version_": 1560655968822362000
}
]
But I use
import scorched
si = scorched.SolrInterface("http://localhost:8983/solr/chatbot")
document = {"id" : ID,
"post" : arg
}
si.add(document)
si.commit()
ID is a unique key, but when I run the code above,
if ID are same, it will cover my original data.
How can I fix it?
Try using curl with /update
Example:
$ curl http://localhost:8983/solr/collection_name/update -d '
[
{"id" : "2001187260",
"cmnt" : {"set":"Shy"}
}
]'
Check Here for more details
i am trying to query nested array of objects in mongodb from node js, tried all the solutions but no luck. can anyone please help this on priority?
I have tried following :
{
"name": "Science",
"chapters": [
{
"name": "ScienceChap1",
"tests": [
{
"name": "ScienceChap1Test1",
"id": 1,
"marks": 10,
"duration": 30,
"questions": [
{
"question": "What is the capital city of New Mexico?",
"type": "mcq",
"choice": [
"Guadalajara",
"Albuquerque",
"Santa Fe",
"Taos"
],
"answer": [
"Santa Fe",
"Taos"
]
},
{
"question": "Who is the author of beowulf?",
"type": "notmcq",
"choice": [
"Mark Twain",
"Shakespeare",
"Abraham Lincoln",
"Newton"
],
"answer": [
"Shakespeare"
]
}
]
},
{
"name": "ScienceChap1test2",
"id": 2,
"marks": 20,
"duration": 30,
"questions": [
{
"question": "What is the capital city of New Mexico?",
"type": "mcq",
"choice": [
"Guadalajara",
"Albuquerque",
"Santa Fe",
"Taos"
],
"answer": [
"Santa Fe",
"Taos"
]
},
{
"question": "Who is the author of beowulf?",
"type": "notmcq",
"choice": [
"Mark Twain",
"Shakespeare",
"Abraham Lincoln",
"Newton"
],
"answer": [
"Shakespeare"
]
}
]
}
]
}
]
}
Here is what I've tried so far but still can't get it to work
db.quiz.find({name:"Science"},{"tests":0,chapters:{$elemMatch:{name:"ScienceChap1"}}})
db.quiz.find({ chapters: { $elemMatch: {$elemMatch: { name:"ScienceChap1Test1" } } }})
db.quiz.find({name:"Science"},{chapters:{$elemMatch:{$elemMatch:{name:"ScienceChap1Test1"}}}}) ({ name:"Science"},{ chapters: { $elemMatch: {$elemMatch: { name:"ScienceChap1Test1" } } }})
Aggregation Framework
You can use the aggregation framework to transform and combine documents in a collection to display to the client. You build a pipeline that processes a stream of documents through several building blocks: filtering, projecting, grouping, sorting, etc.
If you want get the mcq type questions from the test named "ScienceChap1Test1", you would do the following:
db.quiz.aggregate(
//Match the documents by query. Search for science course
{"$match":{"name":"Science"}},
//De-normalize the nested array of chapters.
{"$unwind":"$chapters"},
{"$unwind":"$chapters.tests"},
//Match the document with test name Science Chapter
{"$match":{"chapters.tests.name":"ScienceChap1test2"}},
//Unwind nested questions array
{"$unwind":"$chapters.tests.questions"},
//Match questions of type mcq
{"$match":{"chapters.tests.questions.type":"mcq"}}
).pretty()
The result will be:
{
"_id" : ObjectId("5629eb252e95c020d4a0c5a5"),
"name" : "Science",
"chapters" : {
"name" : "ScienceChap1",
"tests" : {
"name" : "ScienceChap1test2",
"id" : 2,
"marks" : 20,
"duration" : 30,
"questions" : {
"question" : "What is the capital city of New Mexico?",
"type" : "mcq",
"choice" : [
"Guadalajara",
"Albuquerque",
"Santa Fe",
"Taos"
],
"answer" : [
"Santa Fe",
"Taos"
]
}
}
}
}
$elemMatch doesn't work for sub documents. You can use the aggregation framework for "array filtering" by using $unwind.
You can delete each line from the bottom of each command in the aggregation pipeline in the above code to observe the pipelines behavior.
You should try the following queries in the mongodb simple javascript shell.
There could be Two Scenarios.
Scenario One
If you simply want to return the documents that contain certain chapter names or test names for example just one argument in find will do.
For the find method the document you want to be returned is specified by the first argument. You could return documents with the name Science by doing this:
db.quiz.find({name:"Science"})
You could specify criteria to match a single embedded document in an array by using $elemMatch. To find a document that has a chapter with the name ScienceChap1. You could do this:
db.quiz.find({"chapters":{"$elemMatch":{"name":"ScienceChap1"}}})
If you wanted your criteria to be a test name then you could use the dot operator like this:
db.quiz.find({"chapters.tests":{"$elemMatch":{"name":"ScienceChap1Test1"}}})
Scenario Two - Specifying Which Keys to Return
If you want to specify which keys to Return you can pass a second argument to find (or findOne) specifying the keys you want. In your case you can search for the document name and then provide which keys to return like so.
db.quiz.find({name:"Science"},{"chapters":1})
//Would return
{
"_id": ObjectId(...),
"chapters": [
"name": "ScienceChap2",
"tests: [..all object content here..]
}
If you only want to return the marks from each test object you can use the dot operator to do so:
db.quiz.find({name:"Science"},{"chapters.tests.marks":1})
//Would return
{
"_id": ObjectId(...),
"chapters": [
"tests: [
{"marks":10},
{"marks":20}
]
}
If you only want to return the questions from each test:
db.quiz.find({name:"Science"},{"chapters.tests.questions":1})
Test these out. I hope these help.
I have a document just like this.
{
"Node": {
"-name": "Dev6",
"Interface": [
{
"-ip": "10.20.18.65",
"-mask": "255.255.255.192"
},
{
"-ip": "10.20.18.129",
"-mask": "255.255.255.192"
}
]
}
}
My perl program is following.
my $dbs_update_Node_by_key ='FOR u IN Node FILTER u._key == #key UPDATE u WITH {
name: #name,
Interface: #Interface
} IN Node';
......
(comments: $inf means [{"-ip","-mask"},{"-ip","-mask"}])
my $bind_args = {
key => $doc->{'_key'},
name => $node_attrs->{'-name'},
Interface => $inf
};
$sth = $itdb->query($dbs_update_Node_by_key)->bind($bind_args)->execute();
It returns "Invalid bind parameter value". I think ArangoDB perl driver didn't support it.
How can I use AQL or REST API to implement it? Thanks!
I think the problem is that
[{"-ip","-mask"},{"-ip","-mask"}]
won't work. When using the curly brackets and member names (e.g. "-ip", "-mask"), there must be a value associated to each member. Using this value instead should work:
[{"-ip": "a.b.c.d", "-mask": "a.b.c.d" }, {"-ip": "a.b.c.d" ,"-mask": "a.b.c.d" }]
Please also note that in your above query, you will update an attribute named "name", whereas in the example document the attribute name is "-name" (with minus sign in front). To use an attribute name with a minus sign at the beginning, it needs to be quoted in backticks in AQL (see below).
Additionally, the example document has attributes "-name" and "Interface" inside a sub-attribute "Node", whereas the UPDATE command will update attributes "name" and "Interface" on the top level of the document.
I have adjusted the query a bit. The following sequence seems to work from the ArangoShell:
db._create("Node");
db.Node.save({
"_key": "test",
"Node": {
"someAttribute": "someValue",
"-name": "Dev6",
"Interface": [
{
"-ip": "10.20.18.65",
"-mask": "255.255.255.192"
},
{
"-ip": "10.20.18.129",
"-mask": "255.255.255.192"
}
]
}
});
dbs_update_Node_by_key = 'FOR u IN Node FILTER u._key == #key ' +
'UPDATE u WITH { Node: { `-name`: #name, Interface: #Interface } } IN Node';
bind_args = {
key: "test",
name: "Dev8",
Interface: [
{
"-ip": "8.8.8.8",
"-mask": "255.255.255.192"
},
{
"-ip": "192.168.0.1",
"-mask": "255.255.255.255"
}
]
};
db._query(dbs_update_Node_by_key, bind_args);
db.Node.toArray();
This will produce:
[
{
"_id" : "Node/test",
"_key" : "test",
"_rev" : "18996044030550",
"Node" : {
"-name" : "Dev8",
"someAttribute" : "someValue",
"Interface" : [
{
"-ip" : "8.8.8.8",
"-mask" : "255.255.255.192"
},
{
"-ip" : "192.168.0.1",
"-mask" : "255.255.255.255"
}
]
}
}
]
I am not sure if this is what you required, but at least it updates the document and overwrites the "Interface" attribute with new values.