Firestore 查询 endBefore 和 endAt 未按预期工作

Firestore query endBefore & endAt not working as expected

我正在使用 Node 10、firebase 8.0、firebase-admin 9.3.0。我已经包含了我的测试代码和客户端 js 版本的副本。

数据

Document ID | name | is_visible
----------- | ---- | ----------
     1      |   a  | true
     2      |   b  | true
     3      |   c  | true
     4      |   d  | true
     5      |   e  | true
     6      |   f  | true
     7      |   g  | true
     8      |   h  | true
     9      |   i  | true

代码

var admin = require("firebase-admin");

const firebaseConfig = {xxx}

admin.initializeApp({
    credential: admin.credential.cert(firebaseConfig)
  });

const getDocs = async () =>{

  try {

    const cursor = await admin.firestore().collection('ordering').doc('5').get();

    const beforeDocs = await admin.firestore().collection('ordering')
    .orderBy("name", "desc")
    .endAt(cursor)
    .limit(2)
    .get()


      beforeDocs.forEach((doc)=> {
        console.log("Doc ID - ",doc.id, ", Name -", doc.get('name'));
      })

    
    const afterDocs = await admin.firestore().collection('ordering')
      .orderBy("name", "desc")
      .startAt(cursor)
      .limit(2)
      .get()


    afterDocs.forEach((doc)=> {
      console.log("Doc ID - ",doc.id, ", Name -", doc.get('name'));
    })

  }
  catch (error) {
    console.error(error);
  }
}

getDocs();

运行 使用 node getDocs.js

期待结果

Doc ID -  6 , Name - f
Doc ID -  5 , Name - e
Doc ID -  5 , Name - e
Doc ID -  4 , Name - d

实际结果

Doc ID -  9 , Name - i
Doc ID -  8 , Name - h
Doc ID -  5 , Name - e
Doc ID -  4 , Name - d

我对 endAt 的临时解决方法是使用 startAt 将顺序反转为“asc”,然后在 QuerySnapshot 中反转 forEach 之前的 docs 数组。

我创建了这个 JS 来显示我的问题,这是我测试集的 运行ning,它非常粗糙,请善待,输出到控制台。

我显然做错了什么,但不确定是什么。

<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-firestore.js"></script>

<body>
  <div id="output">Check the console!</div>
</body>
<script>

  var firebaseConfig = {
    apiKey: "AIzaSyAxLEo7LfABdATToJTMQGae3Vgum_CAlQg",
    authDomain: "bmtestbase.firebaseapp.com",
    databaseURL: "https://bmtestbase.firebaseio.com",
    projectId: "bmtestbase",
    storageBucket: "bmtestbase.appspot.com",
    messagingSenderId: "326028950684",
    appId: "1:326028950684:web:74b55887466c63b4a9c159"
  };

  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
  
const db = firebase.firestore()
   
// Setting the Focus point using a Snapshot 
db.collection('ordering').get()
  .then (docs => {
    docs.forEach(doc => {
          console.log("MYCODE_allDocs: DocID ", doc.id, ", Name ", doc.get('name'))
    })
  })

db.collection('ordering').doc('5').get()
  .then( focusSnapshot => {

    db.collection("ordering")
      .orderBy("name", "asc")
      .endAt(focusSnapshot)
      .limit(2)
      .get()
    .then(docs => {
  
       console.log("MYCODE_endAt_expected:","DocID 4, Name d")
       console.log("MYCODE_endAt_expected:","DocID 5, Name e")      

      docs.forEach(doc => {  
        console.log("MYCODE_endAt:","DocID ", doc.id, ", Name ", doc.get('name'))
      }); 
    })


    db.collection("ordering")
      .orderBy("name", "asc")
      .startAt(focusSnapshot)
      .limit(2)
      .get()
    .then(docs => {

       console.log("MYCODE_startAt_expected:","DocID 5, Name e")
       console.log("MYCODE_startAt_expected:","DocID 6, Name f")      

      docs.forEach(doc => {  
        console.log("MYCODE_startAt:","DocID ", doc.id, ", Name ", doc.get('name'))
      }); 
    })
  
})

</script>

我认为您对 startAt 和 endAt 的期望不正确。我建议查看 documentation.

关于startAt,它说:

Use the startAt() or startAfter() methods to define the start point for a query. The startAt() method includes the start point, while the startAfter() method excludes it.

因此,如果您传递限制为 5 的 startAt() 的快照,您将从该文档开始查询,并获得查询顺序中紧随其后的 4 个文档。

Similarly, use the endAt() or endBefore() methods to define an end point for your query results.

endAt() 限制为 5 会导致查询结果在该文档处停止。因此,除了查询顺序中位于它之前的 4 个文档之外,您还将获得该文档。

根据 firebase 支持,您需要使用 limitToLast with endBefore and endAt

像这样重写您的示例应该可行:

<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.0.0/firebase-firestore.js"></script>

<body>
  <div id="output">Check the console!</div>
</body>
<script>

  var firebaseConfig = {
    apiKey: "AIzaSyAxLEo7LfABdATToJTMQGae3Vgum_CAlQg",
    authDomain: "bmtestbase.firebaseapp.com",
    databaseURL: "https://bmtestbase.firebaseio.com",
    projectId: "bmtestbase",
    storageBucket: "bmtestbase.appspot.com",
    messagingSenderId: "326028950684",
    appId: "1:326028950684:web:74b55887466c63b4a9c159"
  };

  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
  
const db = firebase.firestore()
   
// Setting the Focus point using a Snapshot 
db.collection('ordering').get()
  .then (docs => {
    docs.forEach(doc => {
          console.log("MYCODE_allDocs: DocID ", doc.id, ", Name ", doc.get('name'))
    })
  })

db.collection('ordering').doc('5').get()
  .then( focusSnapshot => {

    db.collection("ordering")
      .orderBy("name", "asc")
      .endAt(focusSnapshot)
      .limitToLast(2)
      .get()
    .then(docs => {
  
       console.log("MYCODE_endAt_expected:","DocID 4, Name d")
       console.log("MYCODE_endAt_expected:","DocID 5, Name e")      

      docs.forEach(doc => {  
        console.log("MYCODE_endAt:","DocID ", doc.id, ", Name ", doc.get('name'))
      }); 
    })


    db.collection("ordering")
      .orderBy("name", "asc")
      .startAt(focusSnapshot)
      .limit(2)
      .get()
    .then(docs => {

       console.log("MYCODE_startAt_expected:","DocID 5, Name e")
       console.log("MYCODE_startAt_expected:","DocID 6, Name f")      

      docs.forEach(doc => {  
        console.log("MYCODE_startAt:","DocID ", doc.id, ", Name ", doc.get('name'))
      }); 
    })
  
})

</script>