How to make multiple IN ["V1", "V3","V5"] query - couchdb

For a documents of that has the following structure
{
"countryCode": "US",
"status" : "Pending"
}
where the countryCode has limited list of options (ISO country codes)
and the status has a limited set of options too I need to select only the documents that
are for the given list of countries basically and given list of statuses
in SQL means it would be something like
countryCode IN ["US","AR", "UK"] AND status IN ["Pending", "Error", "Loading"]
is it at all possible in Cloudant / CouchDB?

With CouchDB's /db/_find, the following selector produces the desired result:
{
"selector":{
"$and":[
{
"countryCode":{
"$in":["US", "AR", "UK"]
}
},
{
"status":{
"$in":["Pending", "Error", "Loading"]
}
}
]
}
}
Condition operators such as $in are specific to a field, and are used to evaluate the value stored in that field.
CURL
curl -H 'Content-Type: application/json' -X POST http://localhost:5984/<db>/_find -d '{"selector":{"$and":[{"countryCode":{"$in":["US", "AR", "UK"]}},{"status":{"$in":["Pending", "Error", "Loading"]}}]}}'

Related

CouchDB Search of Multiple Fields

I am trying to use CouchDB 3.1 for the first time. I'm trying to do a dynamic query where multiple fields can be searched and is totally optional. Example of my data:
{
"_id": "464e9db4d9216e1621b354794a0181d4",
"_rev": "1-fade491c3e255bbbfa60f1d7462fa9a2",
"app_id": "0000001",
"username": "john#gmail.com",
"transaction": "registration",
"customer_name": "John Doe",
"status": "complete",
"request_datetime": "2020-01-31 12:05:00"
}
So what I'm trying to do is, the documents can be searched by "transaction", "transaction" and "app_id", or combination of the fields "app_id" / "username" / "transaction" / "username" / "status" / "request_datetime" based on the search input from the user. (Some of the field such as "app_id" might be null based on the "transaction")
I have tried to make View to search by "app_id" and "transaction" :
function (doc) {
if(doc.transaction && doc.app_id) {
emit([doc.transaction, doc.app_id], doc);
}
}
But this is not gonna work when the app_id itself is null due to key in CouchDB is the index.
So my question is whether this can be achieved using vanilla CouchDB without using GeoCouch or Lucene? Do I need to make different views based on different combination of search fields?
Any help is greatly appreciated. Thank you very much.
With /db/_find, you can define a selector that accepts combination operators and condition operators. This lets you create simple and really complex queries. Given your document structure, such a selector could look as follows.
"selector":{
"$and":[
{
"app_id":{
"$eq":"0000001"
}
},
{
"username":{
"$eq":"john#gmail.com"
}
},
{
"request_datetime": {
"$gte": "2020-01-31 12:00:00",
"$lt": "2020-01-31 13:00:00"
}
}
]
}
The $or operator, combined with $eq and $exists may be used for checking fields that can be null. The $regex operator offers you even much more power.
Here's a simple example using CURL (replace with the name of your database).
curl -H 'Content-Type: application/json' -X POST http://localhost:5984/<db>/_find -d '{"selector":{"username":{"$eq": "john#gmail.com"}}}'

Spotify API field filtering

I'm trying to use field filtering to pick out specific nested fields, and it seems to me like I'm hitting a limit for nesting.
Here's the filter I'm using: items(date_added, track(name, album(artists(name))))
and here's the curl command I'm trying (built with the new developer console):
curl -X "GET" "https://api.spotify.com/v1/users/<user_id>/playlists/<playlist_id>/tracks?fields=items(date_added%2C%20track(name%2C%20album(artists(name))))" -H "Accept: application/json" -H "Content-Type: application/json"
This call works and everything looks good until it gets to the artists field. It doesn't seem to be filtering down artist fields. I just want the artist name in this case. Here's a snippet of what I'm getting back:
"items": [
{
"track": {
"album": {
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/3t69c5VItBx3GCrnkcYHEL"
},
"href": "https://api.spotify.com/v1/artists/3t69c5VItBx3GCrnkcYHEL",
"id": "3t69c5VItBx3GCrnkcYHEL",
"name": "Imagined Herbal Flows",
"type": "artist",
"uri": "spotify:artist:3t69c5VItBx3GCrnkcYHEL"
}
]
},
"name": "Floating"
}
}...
];
As you can see, I'm getting the full artist object. Can someone help me understand why I can't filter the fields for that?

How to use split_on_whitespace in elastic search?

I want to use split_on_whitespace in search query, but couldn't figure it out. Query will have a string like : "hello world". I don't want to split the query word
First of all make sure that the mapping of the field that you want to search is not analysed. So that ES will not analyse the words in the field and store it as a single text.
so your mapping will be something like:
curl -XPUT localhost:9200/index_name -d '{
"mappings": {
"type_name": {
"properties": {
"field_to_search": {
"type": "string",
"index": "not_analyzed"
},
...(other fields)
}
}
}
}
Then you can perform a term query on the field.
curl -XPOST localhost:9200/index_name/type_name/_search -d '{
"query": {
"term": {
"field_to_search": "hello world"
}
}
}
You can take a look at the difference between term query and match query of elasticsearch to understand why term query is required.

Cloudant: How to create an index for "Sort" function?

The problem I am facing is on creating the correct index to query through my Cloudant database. The JSON data structure I am using looks similar to below.
{
"customer" : "123",
"time" : "2014-11-20"
}
I want to sort the documents based on the time. The index query that I used is:
curl -X POST 'https://<user>:<pass>#<user>.cloudant.com/<DB-name>/_index' -d '
{
"index": {
"fields": [
"customer",
"time"
]
}
}'
And the Query that I am using is:
curl -X POST 'https://<user>:<pass>#<user>.cloudant.com/<DB-name>/_find' -d '
{
"selector": {
"customer" : "123"
},
"sort": [
"time"
]
}'
The error code I am getting is "no_usable_index". Can anyone provide some insight into this problem?
Also, what would be different if the time were in the format:
"2014-11-20 11:50:00"? Essentially, I am trying to sort based on date and time. Is this possible?
The error message is telling you that there is no index to perform the sorting, or at least it can't find one. To help it find one, sort on customer and then on time, like so:
curl -X POST 'https://<user>:<pass>#<user>.cloudant.com/<DB-name>/_find' -d '
{
"selector": {
"customer" : "123"
},
"sort": [
"customer",
"time"
]
}'
This query is functionally identical, but now Cloudant Query will find the index.
Regarding your question about the other time format, the time field would still be treated as a string field for the purposes of sorting. In your case, that means you'll get the expected result.

Indexing geospatial in elastic search results in error?

{ title: 'abcccc',
price: 3300,
price_per: 'task',
location: { lat: -33.8756, lon: 151.204 },
description: 'asdfasdf'
}
The above is the JSON that I want to index. However, when I index it, the error is:
{"error":"MapperParsingException[Failed to parse [location]]; nested: ElasticSearchIllegalArgumentException[unknown property [lat]]; ","status":400}
If I remove the "location" field, everything works.
How do I index geo? I read the tutorial and I'm still confused how it works. It should work like this, right...?
You are getting this error message because the field location s not mapped correctly. It's possible that at some point of time, you tried to index a string in this field and it's now mapped as a string. Elasticsearch cannot automatically detect that a field contains a geo_point. It has to be explicitly specified in mapping. Otherwise, Elasticsearch maps such field as a string, number or object depending on the type of geo_point representation that you used in the first indexed record. Once field is added to the mapping, its type can no longer be changed. So, in order to fix the situation, you will need to delete the mapping for this type and create it again. Here is an example of specifying mapping for a geo_point field:
curl -XDELETE "localhost:9200/geo-test/"
echo
# Set proper mapping. Elasticsearch cannot automatically detect that something is a geo_point:
curl -XPUT "localhost:9200/geo-test" -d '{
"settings": {
"index": {
"number_of_replicas" : 0,
"number_of_shards": 1
}
},
"mappings": {
"doc": {
"properties": {
"location" : {
"type" : "geo_point"
}
}
}
}
}'
echo
# Put some test data in Sydney
curl -XPUT "localhost:9200/geo-test/doc/1" -d '{
"title": "abcccc",
"price": 3300,
"price_per": "task",
"location": { "lat": -33.8756, "lon": 151.204 },
"description": "asdfasdf"
}'
curl -XPOST "localhost:9200/geo-test/_refresh"
echo
# Search, and calculate distance to Brisbane
curl -XPOST "localhost:9200/geo-test/doc/_search?pretty=true" -d '{
"query": {
"match_all": {}
},
"script_fields": {
"distance": {
"script": "doc['\''location'\''].arcDistanceInKm(-27.470,153.021)"
}
},
"fields": ["title", "location"]
}
'
echo
Since you don't specify how you parse it, this:
Parsing through JSON in JSON.NET with unknown property names
may bring some light in.

Resources