Find value json array swift - arrays

I'm trying to find a specific value in my JSON.
this my json
[
{
"airportName" : "Simon Mwansa Kapwepwe Intl",
"longitude" : 28.664999999999999,
"geometry" : {
"type" : "Point",
"coordinates" : [
28.664999999999999,
-12.994999999999999
]
},
"countryCode" : "ZMB",
"countryName" : "Zambia",
"latitude" : -12.994999999999999,
"cityName" : "Ndola",
"airportCode" : "FLSK"
},
{
"airportName" : "Mafikeng",
"longitude" : 25.544469444444445,
"geometry" : {
"type" : "Point",
"coordinates" : [
25.544469444444445,
-25.807447222222223
]
},
"countryCode" : "ZAF",
"countryName" : "South African Rep",
"latitude" : -25.807447222222223,
"cityName" : "Mafikeng",
"airportCode" : "FAMM"
}]
now if I write this code it works!
for item in 0...json.count {
i = i+1
if json[i]["airportName"] == "Simon Mwansa Kapwepwe Intl" {
print ("I found it")
}
if I try to pass the parameter to search with a function it doesn't work, swift give me a error say :Binary operator '==' cannot be applied to operands of type 'JSON' and 'String'
func cerca (nomeApt: String){
var i = 0
for item in 0...json.count {
i = i+1
if json[i]["airportName"] == nomeApt { // error I don't know
print ("I found it")
}
}
}
Honestly, I don't know why? any idea how to solve the issue? thanks a lot

You can try to use decodable,
And that will give you a simple array where you can loop and access the properties.
import Foundation
let json = """
[
{
"airportName" : "Simon Mwansa Kapwepwe Intl",
"longitude" : 28.664999999999999,
"geometry" : {
"type" : "Point",
"coordinates" : [
28.664999999999999,
-12.994999999999999
]
},
"countryCode" : "ZMB",
"countryName" : "Zambia",
"latitude" : -12.994999999999999,
"cityName" : "Ndola",
"airportCode" : "FLSK"
},
{
"airportName" : "Mafikeng",
"longitude" : 25.544469444444445,
"geometry" : {
"type" : "Point",
"coordinates" : [
25.544469444444445,
-25.807447222222223
]
},
"countryCode" : "ZAF",
"countryName" : "South African Rep",
"latitude" : -25.807447222222223,
"cityName" : "Mafikeng",
"airportCode" : "FAMM"
}
]
""".data(using: .utf8)!
struct Geometry: Decodable {
var type: String
var coordinates: [Double]
}
struct Airports: Decodable {
var airportName : String
var longitude : Double
var geometry: Geometry
var countryCode : String
var countryName: String
var latitude: Double
var cityName: String
var airportCode :String
}
func findSpecifAirport(airportName: String) -> Bool {
if let myStruct = try? JSONDecoder().decode([JsonDecoder].self, from: json) {
let foundSpecific = myStruct.filter { $0.airportName == airportName }
return !foundSpecific.isEmpty;
}
return false
}
you could use it like this
let hasFoundIt = findSpecifAirport(airportName: "Simon Mwansa Kapwepwe Intl")

Convert json to string, change the line to:
if json[i]["airportName"] as? String == nomeApt {

Related

Query to update an array field by using another array field of same document in mongodb

Scenario
I've the following document from Chat collection with an array of messages and members in the chat.
And for each message, there will be status field which will store the delivered and read timestamp with respect to users.
{
"_id" : ObjectId("60679797b4365465745065b2"),
"members" : [
ObjectId("604e02033f4fc07b6b82771c"),
ObjectId("6056ef4630d7b103d8043abd"),
ObjectId("6031e3dce8934f11f8c9a79c")
],
"isGroup" : true,
"createdAt" : 1617401743720.0,
"updatedAt" : 1617436504453.0,
"messages" : [
{
"createdAt" : 1617401743719.0,
"updatedAt" : 1617401743719.0,
"_id" : ObjectId("60679797b4365465745065b3"),
"body" : "This is test message",
"senderId" : ObjectId("6031e3dce8934f11f8c9a79c"),
"status" : []
}
]
}
So, I want to insert the following data, into messages.status array, to know when the message is received/read by the member.
{
receiverId: <member of chat>
deliveredAt: <timestamp>
readAt: <timestamp>
}
Question
How to write a query to insert the above json for each member (except the sender) in the status array by using the data from existing field?
So that, after query, the document should look like this:
{
"_id" : ObjectId("60679797b4365465745065b2"),
"members" : [
ObjectId("604e02033f4fc07b6b82771c"),
ObjectId("6056ef4630d7b103d8043abd"),
ObjectId("6031e3dce8934f11f8c9a79c")
],
"isGroup" : true,
"createdAt" : 1617401743720.0,
"updatedAt" : 1617436504453.0,
"messages" : [
{
"createdAt" : 1617401743719.0,
"updatedAt" : 1617401743719.0,
"_id" : ObjectId("60679797b4365465745065b3"),
"body" : "This is test message",
"senderId" : ObjectId("6031e3dce8934f11f8c9a79c"),
"status" : [{
"receiverId": ObjectId("604e02033f4fc07b6b82771c")
"deliveredAt": <timestamp>
"readAt": <timestamp>
}, {
"receiverId": ObjectId("6056ef4630d7b103d8043abd")
"deliveredAt": <timestamp>
"readAt": <timestamp>
}]
}
]
}
Edit
I'm able to do this for static data.
Link: https://mongoplayground.net/p/LgVPfRoXL5p
For easy understanding: I've to map the members array and insert it into the status field of the messages
MongoDB Version: 4.0.5
You can use the $function operator to define custom functions to implement behavior not supported by the MongoDB Query Language. So along with updates-with-aggregate-pipeline and $function you can update messages.status array with only receiver's details as shown below:
NOTE: Works only with MongoDB version >= 4.4.
Try this:
let messageId = ObjectId("60679797b4365465745065b3");
db.chats.update(
{ "messages._id": messageId },
[
{
$set: {
"messages": {
$map: {
input: "$messages",
as: "message",
in: {
$cond: {
if: { $eq: ["$$message._id", messageId] },
then: {
$function: {
body: function (message, members) {
message.status = [];
for (let i = 0; i < members.length; i++) {
if (message.senderId.valueOf() != members[i].valueOf()) {
message.status.push({
receiverId: members[i],
deliveredAt: new Date().getTime(),
readAt: new Date().getTime()
})
}
}
return message;
},
args: ["$$message", "$members"],
lang: "js"
}
},
else: "$$message"
}
}
}
}
}
}
]
);
Output:
{
"_id" : ObjectId("60679797b4365465745065b2"),
"members" : [
ObjectId("604e02033f4fc07b6b82771c"),
ObjectId("6056ef4630d7b103d8043abd"),
ObjectId("6031e3dce8934f11f8c9a79c")
],
"isGroup" : true,
"createdAt" : 1617401743720,
"updatedAt" : 1617436504453,
"messages" : [
{
"_id" : ObjectId("60679797b4365465745065b3"),
"createdAt" : 1617401743719,
"updatedAt" : 1617401743719,
"body" : "This is test message",
"senderId" : ObjectId("6031e3dce8934f11f8c9a79c"),
"status" : [
{
"receiverId" : ObjectId("604e02033f4fc07b6b82771c"),
"deliveredAt" : 1617625735318,
"readAt" : 1617625735318
},
{
"receiverId" : ObjectId("6056ef4630d7b103d8043abd"),
"deliveredAt" : 1617625735318,
"readAt" : 1617625735318
}
]
},
{
"_id" : ObjectId("60679797b4365465745065b4"),
"createdAt" : 1617401743719,
"updatedAt" : 1617401743719,
"body" : "This is test message",
"senderId" : ObjectId("6031e3dce8934f11f8c9a79d"),
"status" : [ ]
}
]
}
Demo - https://mongoplayground.net/p/FoOvxXp6nji
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/
The filtered positional operator $[] identifies the array elements that match the arrayFilters conditions for an update operation, e.g.
db.collection.update({
"messages.senderId": "6031e3dce8934f11f8c9a79c" // query
},
{
"$push": {
"messages.$[m].status": [ // push into the matching element of arrayFilters
{
"receiverId": ObjectId("604e02033f4fc07b6b82771c")
},
{
"receiverId": ObjectId("6056ef4630d7b103d8043abd")
}
]
}
},
{
arrayFilters: [
{
"m.senderId": "6031e3dce8934f11f8c9a79c" // matches array element where senderId is 6031e3dce8934f11f8c9a79c
}
]
})
Note- add index to messages.senderId for performance

Aggregating MongoDB, displaying top results from two separate collections

I have am trying to perform an aggregate function on my collection but I can't seem to fit the right query for the job.
My goal is to display the top 2 fastest laps on all maps and show the associated user first name and last name.
Here is my stats collections:
{
"_id" : ObjectId("5c86674d87e8cd468c850c86"),
"lapTime" : "1:32:29",
"map" : "France",
"driver" : [
ObjectId("5c7c499b555fa13f50c9c248")
],
"date" : ISODate("2019-03-11T13:49:01.472Z"),
"__v" : 0
}
{
"_id" : ObjectId("5c8667ec87e8cd468c850c87"),
"lapTime" : "2:32:34",
"map" : "France",
"driver" : [
ObjectId("5c7c499b555fa13f50c9c248")
],
"date" : ISODate("2019-03-11T13:51:40.895Z"),
"__v" : 0
}
{
"_id" : ObjectId("5c86674x87e8Sd567c120c86"),
"lapTime" : "1:12:29",
"map" : "France",
"driver" : [
ObjectId("5c7c499b555fa13f50c9c248")
],
"date" : ISODate("2019-03-11T10:49:01.472Z"),
"__v" : 0
}
{
"_id" : ObjectId("5c8667f887e8cd468c850c88"),
"lapTime" : "1:88:29",
"map" : "Italy",
"driver" : [
ObjectId("5c7c499b555fa13f50c9c248")
],
"date" : ISODate("2019-03-11T13:51:52.727Z"),
"__v" : 0
}
{
"_id" : ObjectId("5c866970c65910291c6f2000"),
"lapTime" : "1:34:29",
"map" : "Italy",
"driver" : [
ObjectId("5c80f78ca0ecdf26c83dfc8a")
],
"date" : ISODate("2019-03-11T13:58:08.135Z"),
"__v" : 0
}
{
"_id" : ObjectId("5c868532b5c50c17b0917f9e"),
"lapTime" : "1:43:33",
"map" : "Italy",
"driver" : [
ObjectId("5c80f78ca0ecdf26c83dfc8a")
],
"date" : ISODate("2019-03-11T15:56:34.869Z"),
"__v" : 0
}
Since I am passing the driver ID by reference here:
"driver":[ObjectId("5c7c499b555fa13f50c9c248")] , I want to display the driver's attributes from my users collection.
Here is one of my user objects:
{
"_id" : ObjectId("5c7c499b555fa13f50c9c248"),
"password" : "$2a$10$L..Pf44/R7yJfNPdikIObe04aiJaY/e94VSKlFscjgYOe49Y7iwJK",
"email" : "john.smith#yahoo.com",
"firstName" : "John",
"lastName" : "Smith",
"laps" : [],
"__v" : 0,
}
Here is what I tried so far:
db.getCollection('stats').aggregate([
{ $group: {
_id: { map: "$map" }, // replace `name` here twice
laps: { $addToSet: "$lapTime" },
driver:{$addToSet: "$driver"},
count: { $sum: 1 }
} },
{$lookup:
{
from: "users",
localField: "firstName",
foreignField: "lastName",
as: "driver"
}},
{ $match: {
count: { $gte: 2 }
} },
{ $sort : { count : -1} },
{ $limit : 10 }
]);
As a result, I am getting drivers as a empty array.
What I am actually trying to achieve is something like this:
{
"_id" : {
"map" : "France"
},
"laps" : [
"Jonathan Smith":"2:32:34",
"Someone Else":"1:32:29"
],
"count" : 2.0
}
I think this should work:-
db.getCollection('stats').aggregate([
{ $unwind: "$driver" },
{$lookup:
{
from: "users",
localField: "driver",
foreignField: "_id",
as: "driver"
}},
{ $group: {
_id: { map: "$map" }, // replace `name` here twice
laps: { $addToSet:
{
lapTime: "$lapTime",
driverName: "$driver.firstName" + "$driver.lastName"
}
},
count: { $sum: 1 }
} },
{ $match: {
count: { $gte: 2 }
} },
{ $sort : { count : -1} },
{ $limit : 10 }
]);

Fetch a field from array MongoDB Meteor

Hi I have the following collection structure:
{
"_id" : "HZw2ktDPm6EWnGaFt",
"createdAt" : ISODate("2017-04-16T17:40:59.055Z"),
"pollName" : "",
"entryOwner" : "eHPeQPMd94MQFNXmg",
"question" : [
{
"name" : "Question 1",
"questionId" : "sdPzbn9SWjE46HtM2"
},
{
"name" : "Question 2",
"questionId" : "vpMrpbJ2LZKMLEYKe"
}
],
"sharedWith" : [
{
"id" : "jjX5EDdqMtcyQwd6h",
"name" : "person 1",
"votes" : 0
},
{
"id" : "b3Ctr6LFZMd9smd4B",
"name" : "person 2",
"votes" : 0
}
],
"voters" : [
{
"voterId" : "eHPeQPMd94MQFNXmg",
"questionId" : "vpMrpbJ2LZKMLEYKe",
"optionId" : "EKnYKXEFBWnr4hnCP",
"peopleId" : "b3Ctr6LFZMd9smd4B"
},
{
"voterId" : "eHPeQPMd94MQFNXmg",
"questionId" : "vpMrpbJ2LZKMLEYKe",
"optionId" : "EKnYKXEFBWnr4hnCP",
"peopleId" : "jjX5EDdqMtcyQwd6h"
},
{
"voterId" : "eHPeQPMd94MQFNXmg",
"questionId" : "sdPzbn9SWjE46HtM2",
"optionId" : "rjYLitibXDJjGYKM7",
"peopleId" : "b3Ctr6LFZMd9smd4B"
},
{
"voterId" : "eHPeQPMd94MQFNXmg",
"questionId" : "Q6JiaGFAi2LRHS7GQ",
"optionId" : "wFoduKp23cSYJJG9i",
"peopleId" : "b3Ctr6LFZMd9smd4B"
}
]
}
I would like to get the value of Voters.peopleId by using these values.
"voterId" : "eHPeQPMd94MQFNXmg",
"questionId" : "vpMrpbJ2LZKMLEYKe",
"optionId" : "EKnYKXEFBWnr4hnCP",
I tried this and it didnt work it returns the whole document but what i want as a return is just one field:
var getPeopleId = Polls.findOne({
_id:this.props.poll._id}, {"voters": {
$elemMatch :{voterId:Meteor.userId(),questionId:selectedQuestionId,optionId:selectedOptionId}}})
Many thanks
You've got $elemMatch in the projection (2nd param) instead of the query (1st param). You also need to project the result to only include the first match. Try:
const poll = Polls.findOne(
{
_id:this.props.poll._id,
voters: {
$elemMatch: {
voterId: Meteor.userId(),
questionId: selectedQuestionId,
optionId: selectedOptionId
}
},{
'voters.$': 1
});
// guard against missing keys or no results
const peopleId = poll && poll.voters && poll.voters.peopleId;

Query on array of array object in mongodb

Following is my product collection in mongodb..
{
"_id" : ObjectId("56d42389db70393cd9f47c22"),
"sku" : "KNITCHURI-BLACK",
"options" : [
{
"sku" : "KNITCHURI-BLACK-M",
"stores" : [
{
"code" : "6",
"quantity" : 0
},
{
"code" : "10",
"quantity" : 26
}
],
"ean_code" : "2709502",
"size" : "M"
},
{
"sku" : "KNITCHURI-BLACK-S"
"stores" : [
{
"code" : "6",
"quantity" : 0
},
{
"code" : "10",
"quantity" : 30
}
],
"size" : "S"
}
]
}
want query on where { 'options.stores.code' : '6' } and { 'options.stores.quantity' : { $gt : 0 } }, How i query on this collection then i got response? Kindly help on this issue..
Here is the two approaches to get documents in Mongoose.
You can change the Mongo query if required as given in the various answers. I have just used your approach for Mongo query.
Approach 1 - Using cursor - Recommended Approach
Approach 2 - Using Query
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var Schema = mongoose.Schema, ObjectId = Schema.ObjectId;
var Store = new Schema({
code : String,
quantity : Number
});
var Option = new Schema({
sku : String,
stores : [ Store ],
ean_code : String,
size : String
});
var productSchema = new Schema({
_id : ObjectId,
sku : String,
options : [ Option ]
});
var Product = mongoose.model('product', productSchema, 'product');
console.log("Cursor Approach #1");
var cursor = Product.find({
'options.stores' : {
$elemMatch : {
code : '6',
quantity : {
$gt : 0
}
}
}
}).cursor();
console.log("Curosr Results***************************************");
cursor.on('data', function(doc) {
console.log("Getting doc using cursor ==========>" + JSON.stringify(doc));
});
cursor.on('close', function() {
console.log("close the cursor");
});
console.log("Query Approach #2");
var query = Product.find({
'options.stores' : {
$elemMatch : {
code : '6',
quantity : {
$gt : 0
}
}
}
});
console.log("Query Results***************************************");
query.exec(function(err, doc) {
if (err) {
console.log(err);
}
console.log("Getting doc using query ==========>" + JSON.stringify(doc));
});
I think you need to unwind options
db.product.aggregate( [
{ $unwind: "$options" }
{ $match: { 'options.stores.code' : '6','options.stores.quantity' : { $gt : 0 }}
] )
As far as I understand the question, you want to find a products that are in stock in stores with code 6. The following query does that:
db.collection.find({"options.stores" : {$elemMatch: {"code" : "6", "quantity" : {$gt : 0}}}});

How to query the firebase database to fetch specific data?

{
"todo" : {
"Kujbghnkj04t56-" : {
"id" : 1,
"tags" : [ {
"name" : "Italy"
}, {
"name" : "Australia"
} ],
"username" : "ABC"
},
"oPikoieew9oR-" : {
"id" : 2,
"tags" : [ {
"name" : "Switzerland"
} ],
"username" : "XYZ"
}
}
}
I am trying to search in Firebase according to tags name. My code is:
var tagRef = new Firebase(FURL+'/todo');
var tagCollection = $firebaseArray(tagRef);
tagCollection.$ref().orderByChild("tags").equalTo("Australia").once("value", function(dataSnapshot){
// code
});`
How can I get the snapshot of all data containing tag name as "Australia"

Resources