How to scroll through elastic query results, python - python

I'm querying my elastic search server and limiting it to 100 results, but there could be a potential of 5000+ results, but for speed I don't want to overload the users connection trying to send it all in bulk.
data = es.search(index=case_to_view, size=100,body={
"query": {
"range" : {
"someRandomFIeld" : {
"gte" : 1,
}
}
}
})
This is doing two things, getting me results that have the field type and only getting the results where that field type exists if its value is greater than equal to 1.
data['hits']['total'] # 5089
How do I let the user get the next lot of results from the same query, ie. The next 100, previous 100, etc

You'll want to utilize the "from" and "size" properties.
You can see it here in the 7.0 documentation.
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-from-size.html
ex :
{
"from" : 0, "size" : 10,
"query" : {
"term" : { "user" : "kimchy" }
}
}

Related

MongoDB - Querying a nested boolean field

I have the following mongoclient query:
db = db.getSiblingDB("test-db");
hosts = db.getCollection("test-collection")
db.hosts.aggregate([
{$match: {"ip_str": {$in: ["52.217.105.116"]}}}
]);
Which outputs this:
{
"_id" : ObjectId("..."),
"ip_str" : "52.217.105.116",
"data" : [
{"ssl" : {"cert" : {"expired" : "False"}}}
]
}
I'm trying to build the query so it returns a boolean True or False depending on the value of the ssl.cert.expired field. I'm not quite sure how to do this though. I've had a look into the $lookup and $where operators, but am not overly familiar with querying nested objects in Mongo yet.
As the data is an array, in order to get the (first) element of the nested expired, you should work with $arrayElemAt and provide an index as 0 to indicate the first element.
{
$project: {
ip_str: 1,
expired: {
$arrayElemAt: [
"$data.ssl.cert.expired",
0
]
}
}
}
Demo # Mongo Playgound

pymongo update multiple fields in a document only if one field value is greater than the current

Using pymongo, I only want to update certain fields of a document if a specific field is greater.
for example, the original document could look something like this for an auction application
{
"_id": ".....",
"highestbid": 100,
"highestbidder": "joe",
"someotherinfo": "...."
}
suppose now a bidder named john outbid joe at 200. How could I use collection.update() to update both the highestbid field and highestbidder field only if the new bid is higher than highestbid, while leaving someotherinfo alone?
I know I can use $max to insert the higher of the two bid values, but I'm not sure how to update highestbidder depending on the result of highestbid all in a single .update(), if it is even possible.
You need to use the operator $lt to verify that old bid is less then the new one to update your document, this should solve your problem:
db.collection.update({
"highestbid": {
"$lt": 200
}
}, {
"$set": {
"highestbid": 200,
"highestbidder": "jhon"
}
}, {
"multi": false
})
Using pymongo:
db.collection.update_one({
"highestbid": {
"$lt": 200
}
}, {
"$set": {
"highestbid": 200,
"highestbidder": "jhon"
}
})

How to find the count of the number of documents in mongodb using pymongo aggregation?

I'm trying to find the max value of a field from a number of documents and want the output to not only reflect the max value of the field but also the total count of documents that the aggregate query will retrieve.
I'm able to retrieve the "wait" field with the max value that I want with the below query, but am stuck with how to get the count of all the documents that are satisfy the below query(Match field).
db = mongo_client[_MONGO_COLLECTION]
cursor = db.aggregate(
[
{"$match": { "owner": { "$exists": False}}},
{
"$project": {
"wait" : {
"$divide": [{"$subtract": [datetime.now(), "$creationDate"]}, 1000],
}
}
},
{
"$sort" : {
"wait": -1
}
}, {"$limit" : 1}
])
for x in cursor:
print(x)
You can use count method as below:
print(cursor.count())
print(list(cursor))
or
you can add $count pipeline as below:
{
"$count":"count" // the name of count filed
}

How to query PointField - MongoEngine

I was trying to update PointField in my flask app with upsert_one. But it always inserts new document. I know the problem is with the query which I'm passing.
Below is my model.
class Location(db.Document):
location_name = db.StringField(required=True)
geoCoords = db.PointField()
And the update query.
Location.objects(geoCoords=loc["geoCoords"]).upsert_one(location_name=loc["location_name"], geoCoords=loc["geoCoords"])
#loc["geoCoords"] = [77.6309395,12.9539974]
I also tried running get. But I'm getting the error message "Location matching query does not exist." for the below query.
loc = Location.objects(geoCoords=[77.6309395,12.9539974]).get()
I have following entries in my location collection.
> db.location.find()
{ "_id" : ObjectId("59c5019727bae70ad3259e67"), "geoCoords" : { "type" : "Point", "coordinates" : [ 77.6309395, 12.9539974 ] }, "location_name" : "Bengaluru" }
{ "_id" : ObjectId("59c5022d27bae70ad3259ea2"), "geoCoords" : { "type" : "Point", "coordinates" : [ 77.6309395, 12.9539974 ] }, "location_name" : "Bengaluru" }
>
I couldn't find any related information on querying the PointFiled.
To answer to my question. I think there is no way to get the exact points like I have mentioned in the question.
The nearest method works here is to use __near selector. This accepts the range in meters. So, you can give closest range query as per your requirement.
In my case, I gave 100 meters. Which is fine for me.
Example:
Location.objects(geoCoords__near=thelocation["geoCoords"], geoCoords__max_distance=100).upsert_one(location_name=thelocation["location_name"], geoCoords=thelocation["geoCoords"])
Try this:
Location.objects(geoCoords="...").update(location_name=loc["location_name"], geoCoords=loc["geoCoords"])

How to $set sub-sub-array value in MongoDB by pymongo

Data:
{
"_id" : ObjectId("50cda9741d41c81da6000002"),
"template_name" : "common_MH",
"role" : "MH",
"options" : [
{
"sections" : [
{
"tpl_option_name" : "test321",
"tpl_option_type" : "string",
"tpl_default_value" : "test321"
}
],
"tpl_section_name" : "Test"
}
]
}
could I modify tpl_default_value in options.$.section.$.tpl_option_name = 'test321'?
I already try too times, but I can't solve.
please assist me, thanks.
This is a bad schema for doing these kinda of updates, there is a JIRA for multi-level positional operator however it is not yet done: https://jira.mongodb.org/browse/SERVER-831
Ideally you either have to update this client side and then atomically set that section of the array:
$section = {
"tpl_option_name" : "test321",
"tpl_option_type" : "string",
"tpl_default_value" : "test321"
};
db.col.update({}, {$set: {options.$.sections.1: $section}})
Or you need to change your schema. Does the sections really need to be embedded? I noticed that you have a tpl_section_name in the top level but then you are nesting sections within that, it sounds more logical that only one section should be there.
That document would be easier to update.

Categories