在$之外使用$或者$ elemMatch和条件

时间:2017-06-27 18:01:38

标签: javascript node.js mongodb mongoose mongodb-query

我的基本结构是我有User对象,其会话对象包含subjectId和每小时价格。

query.elemMatch("subjects", {
                "id": { $in: subjects },
                "$or": [
                    { "hourly": { $eq: null } }, // this is my issue
                    {
                        "$and": [
                            { "hourly": { $ne: null } },
                            { "hourly": { $gte: price.low, $lte: price.high } }
                        ]
                    }
                ]
            });

我像这样使用elemMatch:

"$or": [
           { 
                "$and": [
                   { "hourly": { $eq: null } },
                   { "defaultHourly": { $gte: price.low, $lte: price.high } } //this doesnt work because default hourly is not a field.
                ]
           },
           {
               "$and": [
                   { "hourly": { $ne: null } },
                   { "hourly": { $gte: price.low, $lte: price.high } }
                ]
            }
       ]
 }); 
elemMatch的第一部分确保我想要的主题是在主题数组中。然后我想按价格过滤。如果用户在每小时字段中为空,我想将defaultHourly与price.low和price.high进行比较。

问题是defaultHourly不是主题中的字段,而是主题父母中的字段,因此我不确定如何访问它。

我想写:

For Each rw In myRange.Rows
    For Each cel In rw.Cells
        For i = LBound(myArray) To UBound(myArray)
            Set oCell = myRange.Find(What:=myArray(i), LookIn:=xlValues, _
                        LookAt:=xlWhole, SearchOrder:=xlByRows, 
                        SearchDirection:=xlNext, _
                        MatchCase:=False, SearchFormat:=False)

            If oCell Is Nothing Then
                sTemp = sTemp & "," & myArray(i)
            Else
                Set oCell = Nothing
            End If
        Next i

        sTemp = Mid(sTemp, 2)

        If Not Len(Trim(sTemp)) = 0 Then
            BookMarksToDelete = Split(sTemp, ",")

            Set wdApp = CreateObject("Word.Application")
            wdApp.Visible = True
            Set wdDoc = wdApp.Documents.Open(FlName)

            For i = LBound(BookMarksToDelete) To UBound(BookMarksToDelete)
                Set pRng = wdDoc.Bookmarks(BookMarksToDelete(i)).Range
                pRng.MoveEnd wdParagraph, 2
                pRng.Delete
            Next i
        End If

        Set wdTable = wdDoc.Tables(1)
        For i = LBound(BookMarksToDelete) To UBound(BookMarksToDelete)
            For Each cell In myRangeRef
                If InStr(1, cell.Value, BookMarksToDelete(i), vbTextCompare) Then 
                    aCell = cell.Offset(, -1).Value
                    stTemp = stTemp & "," & aCell
                End If
            Next cell
        Next i

        stTemp = Mid(stTemp, 2)
        If Not Len(Trim(stTemp)) = 0 Then
            ReturnsToDelete = Split(stTemp, ",")
            For i = LBound(ReturnsToDelete) To UBound(ReturnsToDelete)
                For j = wdTable.Rows.Count To 2 Step -1
                    If Left(wdTable.cell(j, 1).Range.Text, Len(wdTable.cell(j, 1).Range.Text) - 2) = ReturnsToDelete(i) Then wdTable.Rows(j).Delete
                Next j
            Next i
        End If

        With ThisWorkbook.Sheets("Investors Database")
            firstName = .Range("B" & rw)
            lastName = .Range("A" & rw)
            titleName = lastName & ", " & firstName
        End With

        Set tRng = wdDoc.Bookmarks("TitlePageName").Range
            tRng.Text = wdDoc.Bookmarks("TitlePageName").Range.Text & titleName
            wdDoc.Bookmarks.Add "TitlePageName", tRng

        d = "Information Up-To-Date as of " & Date
        Set dRng = wdDoc.Bookmarks("TitlePageDate").Range
            dRng.Text = wdDoc.Bookmarks("TitlePageDate").Range.Text & d
            wdDoc.Bookmarks.Add "TitlePageDate", dRng

        Set wRng = wdApp.ActiveDocument.Bookmarks("FundCommentary").Range
        wRng.Collapse wdCollapseStart
        wRng.InsertBreak wdPageBreak

        Set sRng = wdApp.ActiveDocument.Bookmarks("Disclaimer").Range
        sRng.Collapse wdCollapseStart
        sRng.InsertBreak wdPageBreak

        wdDoc.TablesOfContents(1).Update
        wdDoc.Repaginate

        With wdApp.ActiveDocument
            .SaveAs2 "https://websitefolder//document.docx"
            .Close
        End With

        wdApp.Visible = False

    Next
Next

如何进行多级比较?

1 个答案:

答案 0 :(得分:1)

您在$elemMatch之外写下条件,并将$or放在文档的顶层。这允许应用每个“集合”条件:

User.find({
  "$or": [
     { 
       "defaultHourly": { "$gte": price.low, "$lte": price.high },
       "subjects": {
         "$elemMatch": { 
           "id": { "$in": subjects },
           "hourly": { "$eq": null }
         }
       }
     },
     {
       "subjects": {
         "$elemMatch": {
           "id": { "$in": subjects },
           "hourly": { "$gte": price.low, "$lte": price.high }
         }
       }
     }
  ] 
})

另请注意,不需要$ne,因为“范围”比较实际上会否定null,因为它不会“大于”实际数值。

此外,请注意,所有MongoDB查询表达式都已经是AND条件,例如同一属性上的$gte$lte。因此即使不是必需的,$ne也可以写成:

   "hourly": { "$gte": price.low, "$lte": price.high, "$ne": null }

这消除了对显式$and的任何需求。