How to make $elemMatch work for json array data in mango query? - couchdb

I have a field in my application like below.
{
"Ct": "HH",
Val:{
"Count":"A",
"Branch":"A"
}
}
When I'm trying to retrieve this using below command in CouchDB, I'm unable to retrieve records.
{
"selector" : {
"Val":{
"$elemMatch":{
"Count":"A"
}
}
}

From the CouchDB documentation,$elemMatch[1]
Matches and returns all documents that contain an array field with at
least one element that matches all the specified query criteria.
Val.Count is not an array field so $elemMatch is not appropriate.
Consider the CouchDB documentation regarding subfield queries[2]:
1.3.6.1.3. Subfields
A more complex selector enables you to specify the values for field of
nested objects, or subfields. For example, you might use a standard
JSON structure for specifying a field and subfield.
Example of a field and subfield selector, using a standard JSON
structure:
{
"imdb": {
"rating": 8
}
}
An abbreviated equivalent uses a dot notation to combine the field and
subfield names into a single name.
{
"imdb.rating": 8
}
Specifically,
selector: {
"Val.Count": "A"
}
1 CouchDB: 1.3.6.1.7. Combination Operators
2 CouchDB: 1.3.6.1.3. Subfields

Related

How to sort mongo docs with an array of elements by mongoose model

I am using mongodb and using mongoose to manipulate the database.
Here I have a set of docs that I would like to sort them by numbers of elements in the array.
Is there a way to sort them by its array length, in mongoose?
Below is an example of the db. I would like to sort them by the number of tags. OR by the number of likeBy (which is an array of userId)
You can create an auxiliar field to sort by that field like this:
First $addFields to create the auxiliar field which value is the array size using $size.
Then sort by that value
And $project to not show the auxiliar field.
db.collection.aggregate({
"$addFields": {
"aux_size": {
"$size": "$tags"
}
}
},
{
"$sort": {
"aux_size": 1
}
},
{
"$project": {
"aux_size": 0
}
})
Example here
Also, if you are using mongoose I think you won't need this because the model says tags fields must be an array. But in case the tags fields could be another type (string, number, boolean...) you can use $isArray to set that documents as length 0 (example here) or to filter them (example here)

mongodb aggregate object sort

{
"$match":{
"field":{
"a":"b",
"c":"d"
}
}
}
When I search in this way, it finds the result, but when I search as follows, it does not find it.
{
"$match":{
"field":{
"c":"d",
"a":"b"
}
}
}
From this official document,
Recursively compare key-value pairs in the order that they appear within the BSON object
So for 2 BSON objects to be regarded as "the same", the field orders need to be in the same order too.

Is it possible to index all attributes without knowing exact structure beforehand in arangodb?

I have a collection with simple documents like this
{
key1:value,
key2:value2,
....
}
I would like to index all keys separately .
But the current arangodb UI only provide a list of attributes seperated by comma, eg. [key1,key2] as input. So I have to define those attributes beforehand
Is there something like * to tell arango to index all attributes.
The standard indexes do not support wildcards to index all attributes (and multiple paths in an index definition will create a combined index, not a union of all keys). But you can create an ArangoSearch View and let it index all attributes:
{
"type": "arangosearch",
"links": {
"coll": {
"analyzers": [
"identity"
],
"includeAllFields": true
}
}
}
Then add some documents into the collection coll:
{"foo": 1}
{"bar": 2}
{"baz": {"nested": 3} }
And finally query the View (here called someView), using the default identity Analyzer:
FOR doc IN someView
SEARCH doc.baz.nested == 3
RETURN doc
As you can see, all attributes including nested ones are indexed by the using the includeAllFields option at the top-level.
More info: https://www.arangodb.com/docs/stable/arangosearch.html

Cloudant Search: what are the conditions for using the count facet?

I am trying to set up a search index using Cloudant, but I find the documentation pretty confusing. It states:
FACETING
In order to use facets, all the documents in the index must include all the fields that have faceting enabled. If your documents do not include all the fields, you will receive a bad_request error with the following reason, “dim field_name does not exist.”
If each document does not contain all the fields for facets, it is recommended that you create separate indexes for each field. If you do not create separate indexes for each field, you must include only documents that contain all the fields. Verify that the fields exist in each document using a single if statement.
Counts
The count facet syntax takes a list of fields, and returns the number of query results for each unique value of each named field.
The count operation works only if the indexed values are strings. The indexed values cannot be mixed types. For example, if 100 strings are indexed, and one number, then the index cannot be used for count operations. You can check the type using the typeof operator, and convert using parseInt, parseFloat and .toString() functions.
Specifically, what does it means when "all the documents in the index include all the fields that have faceting enabled".
For example, if my database consists of the following doc:
{
"_id": "mydoc"
"subjects": [ "subject A", "subject B" ]
}
And I write a search index like so:
function (doc) {
for(var i=0; i < doc.subjects.length; i++)
index("hasSubject", doc.subjects[i], {facet: true});
}
Would this be illegal because mydoc doesn't have a field called hasSubject? And when we rewrite the query to look like;
{
"_id": "mydoc"
"hasSubject": true,
"subjects": [ "subject A", "subject B" ]
}
Would that suddenly make it OK...?
So the new documentation is at https://console.ng.bluemix.net/docs/services/Cloudant/api/search.html#faceting ; however, the entry on faceting is the same. So no big deal there.
To answer your question though, I think what the documentation is saying is that all the JSON docs in your database must contain the subjects field, which is what you're declaring you want to facet on in your example.
So I would also consider defining your search index like so:
function (doc) {
if (doc.subjects) {
for(var i=0; i < doc.subjects.length; i++) {
if (typeof doc.subjects[i] == "string") {
index("hasSubject", doc.subjects[i], {facet: true});
}
}
}
}
And if you had a doc like this in your database:
{
"_id": "mydoc"
"hasSubject": true,
}
I think that would suddenly make your facets NOT ok.

CouchDb view - key in a list

I Want to query CouchDB and I have a specific need : my query should return the name field of documents corresponding to this condition : the id is equal or contained in a document filed (a list).
For example, the field output is the following :
"output": [
"doc_s100",
"doc_s101",
"doc_s102",
"doc_s103",
],
I want to get all the documents having in their output field "doc_s102" for example.
I wrote a view in a design document :
"backward_by_docid": {
"map": "function(doc) {if(doc.output) emit(doc.output, doc.name)}"
}
but this view works only when I have a unique value in the output field.
How can I resolve this query ?
Thanks !
you have to iterate over the array:
if(doc.output) {
for (var curOutput in doc.output) {
emit (doc.output[curOutput],doc.name);
}
}
make sure that output always is an array (at least [])
.. and, of course use key="xx" instead key=["xxx"]

Resources