Mongodb Запрос массива со структурой, превышающей слово - PullRequest
0 голосов
/ 25 апреля 2018

Если у вас есть массив в mongodb следующим образом:

"tokens": [
{
  "index": 1,
  "word": "I",
  "originalText": "I",
  "lemma": "I",
  "characterOffsetBegin": 0,
  "characterOffsetEnd": 5,
  "pos": "NNP",
  "ner": "PERSON",
  "before": "",
  "after": " "
},
{
  "index": 2,
  "word": "played",
  "originalText": "played",
  "lemma": "play",
  "characterOffsetBegin": 6,
  "characterOffsetEnd": 11,
  "pos": "VBZ",
  "ner": "O",
  "before": " ",
  "after": " "
},
{
  "index": 3,
  "word": "football",
  "originalText": "football",
  "lemma": "football",
  "characterOffsetBegin": 22,
  "characterOffsetEnd": 24,
  "pos": "IN",
  "ner": "O",
  "before": " ",
  "after": " "
}
]

и я хочу запросить этот массив следующим образом:

Мне нужно проверить, есть ли (word:I) и (word which contains word:regex(p.*) and pos:VBZ) в этом массиве или нет? если да, мне нужно вернуть этот массив.

$elemMatch не помогло, так как я ищу два условия в этом массиве {"word":"I" and ("word":/p.* and "pos":"VBZ") вместе и в порядке

Кто-нибудь может мне помочь в этом вопросе?

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

ОК, я думаю, что я получаю то, что вы хотите, и это немного сложно, потому что:

  1. Если бы у вас не было поля index, вы бы полагались на порядок элементов массивачто является плохой практикой
  2. Приведенное ниже решение не является универсальным, и его будет сложно изменить, если вам нужны дополнительные параметры (например, более 2 элементов, более сложное регулярное выражение).

В этом решении я хотел добиться того, чтобы $filter соответствовал элементам и проверял, являются ли отфильтрованные индексы $subtract в 1, что означает, что они в порядке:

db.test.aggregate([
    {
        $addFields: {
            filtered_tokens: {
                $filter: {
                    input: '$tokens',
                    as: 'token',
                    cond: {
                        $or: [
                            {
                                $eq: ['$$token.word', 'I']
                            },
                            {
                                $and: [
                                    {
                                        $eq: [{$substr: ['$$token.word', 0, 1]}, 'p']
                                    },
                                    {
                                        $eq: ['$$token.pos', 'VBZ']
                                    }
                                ]                            
                            }
                        ]
                    }
                }
            }
        }
    },
    {
        $match: {
            filtered_tokens: {$size: 2}
        }
    },
    {
        $addFields: {
            filtered_tokens: {
                $subtract: [
                    {
                        $arrayElemAt: ['$filtered_tokens.index', 1]
                    },
                    {
                        $arrayElemAt: ['$filtered_tokens.index', 0]
                    }
                ]
            }
        }
    },
    {
        $match: {
            filtered_tokens: 1
        }
    }
])
0 голосов
/ 25 апреля 2018

Я не уверен, что понял, что вам нужно, но я думаю, что это то, что вы ищете:

db.test.find({
    $and: [
        {
            'tokens.word': 'I'
        },
        {
            tokens: {
                $elemMatch: {
                    word: /p.*/,
                    pos: 'VBZ'
                }
            }
        }
    ]
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...