Как написать запрос для получения значений на основе двух зависимых входных переменных в MongoDB?

У меня есть коллекция mongoDB, содержащая документы JSON в следующем формате. Это всего лишь образец, а не полный документ.

{
    "_id": ObjectId("555ba8a6ae96b63b98969192"),
    "toptags": {
        "@attr": {
            "artist": "Rihanna"
        },
        "tag": [
            {
                "count": "100",
                "name": "pop",
                "url": "http://www.last.fm/tag/pop"
            },
            {
                "count": "89",
                "name": "rnb",
                "url": "http://www.last.fm/tag/rnb"
            },
            {
                "count": "60",
                "name": "female vocalists",
                "url": "http://www.last.fm/tag/female%20vocalists"
            },
            {
                "count": "55",
                "name": "dance",
                "url": "http://www.last.fm/tag/dance"
            },
            {
                "count": "40",
                "name": "Hip-Hop",
                "url": "http://www.last.fm/tag/hip-hop"
            },
            {
                "count": "21",
                "name": "Rihanna",
                "url": "http://www.last.fm/tag/rihanna"
            },
      ]
      }
}

В моей коллекции сотни подобных документов. Я хочу написать запрос, который будет возвращать имена «артистов», которые имеют заданный набор тегов, а значения «количества» этих тегов больше заданного значения.

Это два запроса, которые я пробовал до сих пор

  1. collection_name.find({'$and': [{"toptags.tag.name":tag_array},
                                   {"toptags.tag.count":{'$gte':count_value}}]},
                         {"_id":"1","[email protected]":"1"})
    
  2. collection_name.find({"toptags.artist":
                            {$all : [{"$elemMatch" : 
                                        {"name":tag_array, 
                                         "count": {'$gt': count_value}}},]})
    

Ни один из вышеперечисленных запросов не работает. Я понимаю, что первый в корне неверен, потому что он не принимает значение "count" для тегов, переданных в качестве параметра. Но второй, я думаю, должен работать. Но я думаю, что мой синтаксис неверен. Где я ошибаюсь?


person nixtish    schedule 21.05.2015    source источник
comment
Если вы хотите узнать $gt запрос по Count полям, измените тип данных Count String на number   -  person Yogesh    schedule 21.05.2015
comment
Кроме того, почему @attr отсутствует при запросе к БД?   -  person Sylvain Leroux    schedule 21.05.2015
comment
@SylvainLeroux Что касается того, почему @attr отсутствует. Есть некоторое несоответствие с его использованием. Это требуется при попытке получить имена исполнителей, но не при обращении к значениям тегов. Но второй запрос выше должен иметь @attr, вы правы.   -  person nixtish    schedule 21.05.2015


Ответы (1)


Насколько я понимаю:

  • У вас есть массив тегов для сопоставления;
  • Вы принимаете во внимание только теги выше определенного порога.

Как предложил @yogesh в комментарии, вы должны сначала убедиться, что количество ваших тегов является числом. Не как струна. После этого вы должны построить свой запрос на основе списка тегов. Что-то например, что может быть:

> THRESHOLD=50
> TAGS=['dance', 'rnb']
> for (idx in TAGS) {
    QTAGS[idx]={"$elemMatch": {"name":TAGS[idx], "count":{"$gt": THRESHOLD}}}
  }
> QTAGS
[
    {
        "$elemMatch" : {
            "name" : "dance",
            "count" : {
                "$gt" : 50
            }
        }
    },
    {
        "$elemMatch" : {
            "name" : "rnb",
            "count" : {
                "$gt" : 50
            }
        }
    }
]

Теперь вы можете запросить свою БД:

> db.w.find({"toptags.tag": { "$all": QTAGS}})
{ "_id" : ObjectId("555ba8a6ae96b63b98969192"), "toptags" : { "@attr" : { "artist" : "Rihanna" }, "tag" : [ { "count" : 100, "name" : "pop", "url" : "http://www.last.fm/tag/pop" }, { "count" : 89, "name" : "rnb", "url" : "http://www.last.fm/tag/rnb" }, { "count" : 60, "name" : "female vocalists", "url" : "http://www.last.fm/tag/female%20vocalists" }, { "count" : 55, "name" : "dance", "url" : "http://www.last.fm/tag/dance" }, { "count" : 40, "name" : "Hip-Hop", "url" : "http://www.last.fm/tag/hip-hop" }, { "count" : 21, "name" : "Rihanna", "url" : "http://www.last.fm/tag/rihanna" } ] } }

Поднимите порог и сделайте все это снова, и в итоге вы ничего не выберете:

> THRESHOLD=100
> for (idx in TAGS) {   QTAGS[idx]={"$elemMatch": {"name":TAGS[idx], "count":{"$gt": THRESHOLD}}} }
> db.w.find({"toptags.tag": { "$all": QTAGS}})
> // nothing
person Sylvain Leroux    schedule 21.05.2015
comment
QTAGS - это опечатка, должно быть TAGS, но я думаю, что понял идею. Спасибо - person nixtish; 22.05.2015
comment
@никстиш ??? Я так не думаю -- даже если я согласен, что имя не обязательно лучшее: TAGS - это массив тегов; QTAGS — это часть Query для получения TAGS. - person Sylvain Leroux; 22.05.2015