MongoDB Atlas search with Array of Numbers

How can I perform search operations on type Array of numbers?

Hi @Sagar942150 and welcome in the MongoDB Community :muscle: !

Please provide an example of your document and expected result if you want a detailed answer. It’s too vague.

Here is an example based on what I understand from your question:

test:PRIMARY> db.c.insert({array:[1,2,3]})
WriteResult({ "nInserted" : 1 })
test:PRIMARY> db.c.find({array:1})
{ "_id" : ObjectId("5f84717525fa89f1696c3941"), "array" : [ 1, 2, 3 ] }

Here are more resources that hopefully will help you:

I hope this helps.

Cheers,
Maxime.

@MaBeuLux88 He speaking about Atlas Search not MongoDB :wink:

@Sagar942150 Today we cannot search in array of number in $search.
You have to convert your number array to string array.

Like this.

[1,2,3] => ['1','2','3']

Make a mappings for search like string:

{
  "mappings": {
    "dynamic": false,
    "fields": {
      "ArrayNumbersField": {
        "analyzer": "lucene.keyword",
        "searchAnalyzer": "lucene.keyword",
        "type": "string"
      }
    }
  }
}

Make $search with filter for my example and every number you want to search add new filter:

This query will find all documents with as minimum 1 or 2 in “ArrayNumbersField” ( You can update minimumShouldMatch if you want all number required for your search :

[
    {
        "$search": {
            "index": "SearchIndex1",
            "compound": {
                "filter": [
                    {
                        "compound": {
                            "should": [
                                {
                                    "phrase": {
                                        "path": "ArrayNumbersField",
                                        "query": "1"
                                    }
                                },
                                {
                                    "phrase": {
                                        "path": "ArrayNumbersField",
                                        "query": "2"
                                    }
                                }
                            ],
                            "minimumShouldMatch": 1
                        }
                    }
                ]
            }
        }
    }
]

I hope this will help you :wink:

Hi, Thanks for replying. Actually my question is for mongodb Atlas search query as per there documentation we can’t apply search on array of number type is there a way we can deal with such scenario.

It didn’t work for me my collection having a property as grades:[1, 2] it won’t return anything

@Sagar942150

Just convert this colum of array of number, by array of string. ( with all documents in your collection )
And when you insert new document dont forget to convert your array of number !

[1,2] => ['1','2']

It’s same just need to convert ( String Value) when you make your query to get numbers ( Numeric Value ).

And for make search and get array of numeric value, you can use aggregation pipeline to make your query -

  • $search with $compound and $phrase ( like my first example )
  • $project with $map and $toInt. With this your final result was array of numeric value ! :slight_smile:

Oops! :smiley:
Looks like I got tricked and I read too fast here :frowning:!

Actually, the search should return something with reference to the above code.
$search with $compound and $phrase — It is not working

Wait 1 hour i will make you a full example :wink:

Sure, will wait for your response!!!

Sorry for time :slight_smile:

I have created new collections with two documents:

{"name":"document1","array":["1","2","3"]} 
{"name":"document2","array":["3","4","5"]}

Make search Index mappings:

{
  "mappings": {
    "dynamic": false,
    "fields": {
      "array": {
        "analyzer": "lucene.keyword",
        "searchAnalyzer": "lucene.keyword",
        "type": "string"
      }
    }
  }
}

And make an aggregation with searching 2 and 4:

[{$search: {
  index: 'default',
  compound: {
    filter: [
      {
        compound: {
          should: [
            {
              phrase: {
                path: 'array',
                query: '2'
              }
            },
            {
              phrase: {
                path: 'array',
                query: '4'
              }
            }
          ],
          minimumShouldMatch: 1
        }
      }
    ]
  }
}}]

This return my two documents:

And to get Int value in result array of number you can use $project in your pipeline like this :slight_smile:

[{$search: {
  index: 'default',
  compound: {
    filter: [
      {
        compound: {
          should: [
            {
              phrase: {
                path: 'array',
                query: '2'
              }
            },
            {
              phrase: {
                path: 'array',
                query: '4'
              }
            }
          ],
          minimumShouldMatch: 1
        }
      }
    ]
  }
}}, {
         $project: { 
            name: 1,
            array:
            {
              $map:
                 {
                   input: "$array",
                   as: "grade",
                   in: { $toInt: "$$grade" }
                 }
            }
         }
}]

I cant do more to help you now :stuck_out_tongue:

2 Likes

It’s ok things take time :wink: Thank you for your help but actually as I previously said my collection is having array of number array = [1,2,3,4,5] and I have to perform an operation on this array

You juste have to convert all your documents like this:

array = [1,2,3,4,5] => array = ['1','2','3','4','5']

I will give you my scrypt python to do this :wink: ( You can change query object to apply on specific documents ! )

query = {}
print(lots.count(query))


def idlimit(page_size, skip=None, query=None):
    """Function returns `page_size` number of documents after last_id
    and the new last_id.
    """
    if query is None:
        query = {}
    if skip is None:
        cursor = lots.find(query).limit(
            page_size)
    else:
        cursor = lots.find(query).skip(skip).limit(page_size)

    data = [x for x in cursor]

    if not data:
        return None, None

    if skip is None:
        skip = page_size
    else:
        skip += page_size

    return data, skip


data, skip = idlimit(100, query=query)
count = 0

while skip is not None:
    if data is not None:
        for item in data:
            if len(item['array']) > 0:
                array = list(map(str, item['array']))
                lots.update_one({"_id": item['_id']},
                                {'$set': {'array': array}})
    count += len(data)
    data, skip = idlimit(100, skip=skip, query=query)
    print(count)

Thanks !!! I have added a duplicate field with array of string

Yes this was another solution also :slight_smile:
No problem ! :wink: